all posts

Adding OpenID to your web site in conjunction with ASP.NET Membership

Published to Blog on 18 Jul 2008

AspDotNetMVC_OpenIdLoginI recently added membership, accounts, login, etc. to the AspDotNetMVC site. While doing so I decided I wanted to support OpenID, too. However, I didn’t want to go with only OpenID because I needed ASP.NET Membership in place to work in conjunction with another application, a Kigg site used as a service for rating content on the AspDotNetMVC site. I could have probably converted the Kigg code base to use OpenID but I also wanted to allow people who may not have OpenID to create traditional accounts on the site without signing up for OpenID. Following are the steps I took to implement an OpenID login and integrate it with “traditional ASP.NET” membership. Follow these six steps and you can do the same.

1. Download the awesome C# OpenID library, DotNetOpenId from Google Code, and add it as a reference in your project. This is a great open source library developed by Andrew Arnott, Jason Alexander, Scott Watermasysk, Scott Hanselman, Joe Brinkman and others. It seriously does all the heavy lifting, comes with some good examples, and Andrew Arnott is doing a great job of making posts about fringe cases on his blog.

2. Add some nice usability features to your OpenID login. Go to ID Selector, create an account and grab the couple of lines of JavaScript to create the cool OpenID service selector shown in the image at right.

Did I mention that this is so easy that I don’t know why everyone isn’t supporting OpenID? Going forward I will be doing so in every new site that I create and I’ll retrofit existing sites when I get the chance.AspDotNetMVC_OpenIdLogin2

3. Read the following articles:

After reading the above you will have a pretty good understanding of how to add OpenID to your site. Some of the code examples in the earlier 3 posts by Andrew are a little out of date. As of the writing of this post the code provided in Hanselman’s blog post are the most up to date. Go ahead and read the two “MVC” posts by Andrew even if you are not interested in ASP.NET MVC. The concepts displayed in those posts can be used anywhere. In fact, it was in of those posts where I found my inspiration for overcoming my next hurdle.

The only thing that was missing for me was integration with ASP.NET membership. I actually found very little information for accomplishing this. I found quite a lot of questions asking how to do it, but most of the answers were just more questions asking why you would want to do it.

4. Create your login form (or user control or composite server control or whatever you prefer). In my case I created a user control that holds just the fields necessary for OpenID login and the logic behind them. Doing so allows me to drop that control into any existing login page (shown in image above) or my existing create account page or anywhere else I want to use it. Make sure you add the javascript for the ID Selector.

For allowing traditional ASP.NET membership login and user account creation I just dropped the basic out of the box controls on the page.

5. Wire up the login submit button. I did something like below, which is very similar to examples that Andrew and Scott Hanselman provided. Basically I’m just telling the OpenID provider that I need the user’s email and nickname (for use in the next step):

protected void loginButton_Click(object sender, EventArgs e) {
  if (!openidValidator.IsValid) return; // don't login if custom validation failed.
  OpenIdRelyingParty openid = new OpenIdRelyingParty();
  try {
    IAuthenticationRequest request = openid.CreateRequest(openid_identifier.Text);
    ClaimsRequest fetch = new ClaimsRequest();
    fetch.Nickname = DemandLevel.Require;
    fetch.Email = DemandLevel.Require;
    request.AddExtension(fetch);
    request.RedirectToProvider();
  } catch (OpenIdException ex) {
    // The user probably entered an Identifier that
    // was not a valid OpenID endpoint.
    openidValidator.Text = ex.Message;
    openidValidator.IsValid = false;
  }
}

6. Handle the response from the OpenID provider. This snippet of code is part of the login process and expands upon examples from Andrew Arnott’s and Scott Hanselman’s posts linked to previously.

Here I’m pulling the alias and email address that I requested in the previous step. With that information I check to see if the user already exists in the ASP.NET membership datastore. If not I will create a Membership account for them using their OpenID URI as their username. When I create the account you can see that I’m generating a random string for the user’s password field and password answer field. You’ll also see that I’m adding “This is an OpenID account. You should log in with your OpenID.” as the password question. That way if a user forgets they used OpenID and tries to login through the traditional username/password login form and selects that they forgot their password when the login doesn’t work, he or she will get a reminder about their OpenID in the form of the password question. I know it’s a hack, but it works for now for my modest needs and I’m happy with it.

Next you’ll see that after I create the Membership User I then set the user’s “comment” field to their Nickname. This is because the “Hello, Username. Welcome back to the site.” message at the top of the page would normally display the user’s “username”. In the case of OpenID users their username would be their OpenID URI - something like: http://danhounshell.openidprovidername.com/. That’s a bit ugly and I’d rather use the Nickname that I asked from then when they logged in with OpenID. By shoving the Nickname into the comments field I can first check to see if it has a value and if so use it in the display rather than their username. If it doesn’t have a value then I can default to the username. So now using my previous example it will say “Hello, DanHounshell. Welcome back to the site.” This same thing could be accomplished in a couple of other ways. Throwing the nickname into the session object or putting it in a cookie are other reasonable alternatives. In my case I don’t use the comments field for anything else so once again - I know it’s a hack, but it works for now for my modest needs and I’m happy with it. Plus it’s easy to get to by just writing “user.Comment”. Thinking about it, it might be nice to write an extension method for MembershipUser called DisplayName that determines whether to use the user.Comment property or the user.Username property.

Finally, I just call FormsAuthentication.RedirectFromLoginPage() passing in their OpenID URI that they provided, logging them into the site.

case AuthenticationStatus.Authenticated:
  ClaimsResponse fetch = openid.Response.GetExtension(typeof(ClaimsResponse)) as ClaimsResponse;
  string alias = fetch.Nickname;
  string email = fetch.Email;
  if (string.IsNullOrEmpty(alias))
    alias = openid.Response.ClaimedIdentifier;
  if (string.IsNullOrEmpty(email))
    email = openid.Response.ClaimedIdentifier;

  //Now see if the user already exists, if not create them
  if (Membership.GetUser(openid.Response.ClaimedIdentifier) == null)
  {
    MembershipCreateStatus membershipCreateStatus;
    MembershipUser user = Membership.CreateUser(openid.Response.ClaimedIdentifier,
      Common.GetRandomString(5,7),
      email,
      "This is an OpenID account. You should log in with your OpenID.",
      Common.GetRandomString(5,7),
      true,
      out membershipCreateStatus);
    if (membershipCreateStatus != MembershipCreateStatus.Success)
    {
      loginFailedLabel.Text += ": Unsuccessful creation of Account: " \+ membershipCreateStatus.ToString();
      loginFailedLabel.Visible = true;
      break;
    }
    user.Comment = alias;
    Membership.UpdateUser(user);
  }

  // Use FormsAuthentication to tell ASP.NET that the user is now logged in,
  // with the OpenID Claimed Identifier as their username.

  FormsAuthentication.RedirectFromLoginPage(openid.Response.ClaimedIdentifier, chkRememberMe.Checked);

  break;

That’s all there is to it. Now you can allow your user’s to choose whether they’d like to create an account on your site by creating a new username and password or by using their new or existing OpenID. The bonus with this method is that it allows you to add OpenID support to an existing site that already has traditional membership without breaking anything.

Enjoy and let me know if you have any questions or comments.

Update: October 09, 2008 -  I posted a sample web application that uses the OpenID login control described in this post.


Dan Hounshell
Web geek, nerd, amateur maker. Likes: apis, node, motorcycles, sports, chickens, watches, food, Nashville, Savannah, Cincinnati and family.
Dan Hounshell on Twitter


  • On 19 Jul 2008 "Dave Burke"" said:
    Everyman Links for July 20, 2008
  • On 20 Jul 2008 "Dew Drop - July 20, 2008 | Alvin Ashcraft's Morning Dew"" said:
    Pingback from Dew Drop - July 20, 2008 | Alvin Ashcraft's Morning Dew
  • On 20 Jul 2008 "TrackBack"" said:
  • On 20 Jul 2008 "Reflective Perspective - Chris Alcock » The Morning Brew 140"" said:
    Pingback from Reflective Perspective - Chris Alcock » The Morning Brew 140
  • On 21 Jul 2008 "DotNetKicks.com"" said:
    You've been kicked (a good thing) - Trackback from DotNetKicks.com
  • On 21 Jul 2008 "TrackBack"" said:
  • On 21 Jul 2008 "Justin Kohnen"" said:
    Wicked sweet post Dan. Really helps me address questions I've had with ASP.NET and OpenID. Thanks much for sharing. Do you have any plans to reason a sample/example project? I just a bit curious where and how exactly you "handle the response from OpenID?" I don't see a callback URL. Once again, great post. Very informative.
  • On 21 Jul 2008 "DCSHosts.com"" said:
    Adding OpenID to your web site in conjunction with ASP.NET Membership...
  • On 21 Jul 2008 "Dan Hounshell"" said:
    Justin, check out Andrew Arnott's example in this post blog.nerdbank.net/.../how-to-add-openid-to-your-aspnet-forms.html I'm doing the exact same thing in my Page_Load, checking to see if the request is a response from the OpenID provider (the second code snippet above is an extension of that same code). The DotNetOpenID library must handle sending the callback Url and gathering the response.
  • On 21 Jul 2008 "TrackBack"" said:
  • On 26 Jul 2008 "Blue Onion Software - Onion Peels Blog - Friday Links 9"" said:
    Pingback from Blue Onion Software - Onion Peels Blog - Friday Links 9
  • On 5 Aug 2008 "Jeff"" said:
    Good article. Nice reference material. Thanks. Any chance you care to share the user control and code you created for the login form?
  • On 6 Aug 2008 "Jeff"" said:
    Dan, are you using roles at all as well and if so have you noticed any issues between OpenId and the roles and roles provider?
  • On 11 Aug 2008 "Dan Hounshell"" said:
    Jeff, not for everyone who signs up. In my case as long as the user is authenticated is all that I care about. I am using roles specifically for my account using OpenId, though. I have not noticed any issues. I am able to see extended functionality (only available to admins) when I login with that account. Sure, I'll share the user control I created for my OpenId login form. It's nothing fancy and I showed most of the code in the article above, but I will zip it up and share it for completeness sake. I'll append the article with a link to a zip file when I get a chance to scrub it, package it up, and upload it.
  • On 29 Sep 2008 "Jeff"" said:
    Have you had a chance to set up a demo project with the login user control you created?
  • On 30 Sep 2008 "Jeff"" said:
    Hey Dan, Where can I find Common.GetRandomString? Is this from a library you've written personally or where is it at?
  • On 1 Oct 2008 "ScottGu's Blog"" said:
    Here is the latest in my link-listing series .&160; Also check out my ASP.NET Tips, Tricks and Tutorials
  • On 1 Oct 2008 "Readed By Wrocław NUG members"" said:
    Here is the latest in my link-listing series .&160; Also check out my ASP.NET Tips, Tricks and Tutorials
  • On 2 Oct 2008 "Bookmarks about Openid"" said:
    Pingback from Bookmarks about Openid
  • On 2 Oct 2008 "Dan Hounshell"" said:
    Jeff, I have not put together a sample project, but it shouldn't take long to do so. I'll try to squeeze that in this weekend. Common.GetRandomString(minLength, maxLength) is just a library function that I wrote for that project. Nothing special, but I will include it in the sample project.
  • On 2 Oct 2008 "IHateSpaghetti {code}"" said:
    This blog carnival will be entirely dedicated to web development in MS platform. Scott has published
  • On 5 Oct 2008 "Enlaces de Octubre ASP.NET, ASP.NET MVC, ASP.NET Dynamic Data « Thinking in .NET"" said:
    Pingback from Enlaces de Octubre ASP.NET, ASP.NET MVC, ASP.NET Dynamic Data « Thinking in .NET
  • On 9 Oct 2008 "Digging My Blog - Dan Hounshell"" said:
    A couple of months ago I posted how to add OpenID to your existing web site in conjunction with ASP.NET
  • On 9 Oct 2008 "Dave Burke"" said:
    This is really excellent work, Dan. I've been really debating on whether to go with ASPNET Membership or OpenID for some upcoming projects and your work makes the decision a whole lot easier. Thank you so much!
  • On 10 Oct 2008 "Dan Hounshell"" said:
    Thank you, Dave!
  • On 13 Oct 2008 "Code Monkey Labs"" said:
    This week’s web nuggets is going to be a double dose – last week was busy, busy, busy! Pick of the week 10 Programming Proverbs Every Developer Should Know General Windows Coming to Amazon EC2 Windows developers will soon be able to take advantage
  • On 26 Oct 2008 "Programming"" said:
    Here is the latest in my link-listing series .&160; Also check out my ASP.NET Tips, Tricks and Tutorials
  • On 30 Oct 2008 "Recent Links Tagged With "openid" - JabberTags"" said:
    Pingback from Recent Links Tagged With "openid" - JabberTags
  • On 31 Oct 2008 "Scott"" said:
    Thank you for this. Its exactly what I was looking for and I really appreciate the sample you put out.
  • On 21 Nov 2008 "Steve Trefethen"" said:
    Nice post Dan, special thanks for linking to all of the other relevant content.
  • On 27 Dec 2008 "Tuan"" said:
    I'm so glad I found this post. Thanks, Dan.
  • On 3 Jan 2009 "Kevin Curry"" said:
    FYI, IDSelector has been "upgraded" to RPXNow. Doesn't seem as straightforward as you describe w/ IDSelector Good post.
  • On 30 Jul 2009 "Converting the ASP.NET MVC project into OpenID « Temporarily unnamed blog"" said:
    Pingback from Converting the ASP.NET MVC project into OpenID « Temporarily unnamed blog
  • On 5 Aug 2009 "Peeyush"" said:
    Hi, I followed the steps as mentioned, and everthing worked fine except for the "DotNetOpenAuth.Contracts" library. It gives an error "Could not load file or assembly 'DotNetOpenAuth.Contracts' or one of its dependencies. Strong name signature could not be verified. The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT 0x80131045) " So, I have excluded the file from project, and it works fine. I had to replace OpenIdException with a Exception. Any help out there ? Thanks
  • On 28 Aug 2009 "Nimesh – Perception System"" said:
    Nice Post Informative and useful one I am .Net Developer and I am looking for this Thanks for the great stuff.
  • On 15 Dec 2009 "gaurav"" said:
    Hello Dan, Can you help me implementing OpenID on ASP.net Thanks for your time and consideration, Best, Gaurav gloyalka@gmail.com
  • On 9 Jul 2010 "Integrate Google friend connect (GFC) with existing asp.net membership and website"" said:
    Integrate Google friend connect (GFC) with existing asp.net membership and website
  • On 11 Jul 2010 "Integrate Google friend connect (GFC) with existing asp.net membership and website"" said:
    Integrate Google friend connect (GFC) with existing asp.net membership and website
  • On 8 Aug 2013 "ASP.NET Membership Provider usage in conjunction with an MV | user75"" said:
    Pingback from ASP.NET Membership Provider usage in conjunction with an MV | user75
  • On 28 Aug 2013 "ASP.NET Membership Provider usage in conjunction with an MV | user75"" said:
    Pingback from ASP.NET Membership Provider usage in conjunction with an MV | user75
  • On 30 Aug 2013 "Flexmind Solutions | Login to SharePoint 2010 site using Gmail ID"" said:
    Pingback from Flexmind Solutions | Login to SharePoint 2010 site using Gmail ID
  • On 16 Nov 2013 "OpenID reference problem in asp.net | Jptab"" said:
    Pingback from OpenID reference problem in asp.net | Jptab
  • On 3 Oct 2014 "freebie"" said:
    Adding OpenID to your web site in conjunction with ASP.NET Membership Digging My Blog
  • On 9 Oct 2014 "Symanetc"" said:
    Adding OpenID to your web site in conjunction with ASP.NET Membership Digging My Blog
  • On 14 Nov 2014 "misfit"" said:
    Adding OpenID to your web site in conjunction with ASP.NET Membership Digging My Blog