Today, more and more websites need to identify who their users are. However, in most cases this involves providing authentication, which requires storing the users handle and password. An alternative to this is to allow a third party to authenticate the user and provide your website with the identity. This absolves you from needless worries of securing

the authentication information. An emerging standard for identification is OpenID (http://www.openid.net). OpenID is a shared identity service, allowing users to log into many Internet sites using a single digital identity. This article will explore how to extend the ASP.NET provider model to accept a user’s OpenID.

So why would you want to use OpenID as an authentication provider in your websites? I can think of two very good reasons: reduced IT support costs in resetting and recovering user accounts, and increased customer acquisition. With an OpenID implementation, the IT department is no longer supporting account management, even if that means just supporting the self-service implementation, because that functionality has been completely outsourced to an OpenID Provider. Additionally, it takes less time for a customer to gain access to the privileged areas of your site. The customer can simply supply your registration pipeline with the information they already have stored in their OpenID profile.

OpenID is a shared identity service allowing users to log into many Internet sites using a single digital identity.

Rather than searching the Web for the OpenID standard and trying to implement it from scratch, use one of the two more mature libraries out there. One reason I suggest this is security. These libraries have already eliminated the more obvious and non-obvious security holes in a typical implementation.

The two most popular OpenID implementations for .NET are ExtremeSwank (http://extremeswank.com/aspnet_openid.html) and DotNetOpenID (http://code.google.com/p/dotnetopenid/). Both libraries offer a comparable set of features and are being actively developed. Both of the projects are open source, which means you can study the code to see how they work. DotNetOpenID uses the new BSD license while ExtremeSwank uses the MIT license. The examples in this article will use the DotNetOpenID library; however, it is trivial to replicate the functionality with ExtremeSwank.

The ExteremeSwank and DotNetOpenID libraries have already eliminated the more obvious and non-obvious security holes in a typical implementation.

Getting Authenticated

To get started, create a new Web Application Project and add a reference to the DotNetOpenAuth assembly. By default, Web Applications are set to authenticate using Windows authentication. That will change to Forms authentication, but before making that change, let’s get some base functionality.

Create a new master page named Site.master. Add the following HTML right after the form tag.

<div id=header>
    <asp:LoginName ID="LoginName"
                   runat="server" />
    <asp:LoginStatus ID="LoginStatus"
                     runat="server" />
</div>

This code will add two controls to the master page so you can see who is currently logged in. The LoginName control will display the currently logged in users friendly name. The LoginStatus control will display either a link to the login page or a link to logout the current user. To make it look prettier, add the following style to the head tag. This will put the controls in a silver band and right align them.

<style>
    #header
    {
        float : right;
        background : #c0c0c0;
    }
</style>

Now let’s add the functionality to make these work. Delete the existing Default.aspx page and create a new Content Page from the Site.master. Name it Default.aspx and set it as the start page. Running the application at this point will display your Windows logon and a link to logout.

In order to use an OpenID for authentication, you must configure the Web Application for forms authentication. That is as simple as finding the authentication element in the Web.config and changing the value of the mode attribute to “Forms”. Add a new Content Page named Login.aspx and modify it to look like Listing 1.

The OpenIDLogin control in Login.aspx does all the heavy lifting of requesting the user’s OpenID. When a user clicks the login button, the OpenIDLogin control will forward the request to the OpenID provider and wait for a response. Once the user has authenticated with their OpenID provider, control is returned to the Login.aspx page and the user is logged in to the website.

The additional attributes on the OpenIDLogin control are used to request common properties of all OpenIDs like the user’s e-mail address and their country. During the authentication with the OpenID provider, the user can opt not to forward those details on to the website. For your site, if the user doesn’t provide required pieces of information, you can use a separate registration page to collect that information. For example, I choose not to store my address information with my OpenID, therefore if I authenticate to a site that requires my address, I’ll have to fill that in on a separate page within the site.

Getting Registered

Now that the user can authenticate to your site, you can now collect additional information about the user. As mentioned above, the OpenIDLogin control has a few built-in properties for requesting additional pieces of information from the users OpenID provider.

The code snippet lines below show a few of the elements that OpenID provider can request.

<rp:OpenIdLogin ID="OpenIdLogin1" runat="server"
    CssClass="openid_login" TabIndex="1"
    RequestCountry="Request"
    RequestEmail="Request"
    RequestGender="Require"
    RequestFullName="Request"
    RequestPostalCode="Require"
    RequestTimeZone="Require"
    RememberMeVisible="True" />

Listing 2 and Listing 3 are the HTML and code-behind for the registration page. The Login.aspx page has been modified to store the OpenID authentication result into a session variable that is retrieved in the Page_Load event. Also, in the Page_Load event, if the user is sharing information from the OpenID provider, use the ClaimsResponse object’s properties to populate your controls on the registration form.

In order to store the profile properties in the profile database, you need to add the following section to the Web.Config file.

<profile>
  <properties>
    <add name="FullName" allowAnonymous="false" />
    <add name="Email" allowAnonymous="false" />
    <add name="Newsletter" allowAnonymous="false"
       type="System.Boolean"/>
  </properties>
</profile>

In the btnRegister_Click event of Registration.aspx.cs, do a check using the Membership.GetUser() method to make sure the user doesn’t exist first and then you can create and save the profile.

After you make a few small changes in the Login.aspx page, your site will redirect the user to the registration page if they haven’t supplied the required pieces of information. Listing 4 contains the changes that you should make to Login.aspx.

Conclusions

Hopefully this article has shown how you can add OpenID authentication to your websites. Using one of the available libraries makes it easier to integrate OpenID authentication. You can use the ASP.NET provider model to extend the OpenID authentication with additional details about the user.