There’s a white board next to my kids’ computer on which there is nothing but scribbled credentials for all of the sites that require a unique login and password; most of them comprised of some random forgettable number because all of the memorable names, even the silliest, were already taken by some other kid who I curse now for making me endure the ‘enter and confirm new password’ dialog one more freaking time! But I digress.
But all of the sites my kids visit, and most of the sites I visit aren’t storing sensitive data. O.K, maybe they ask for names and birth dates, I suppose to ensure that the user is of reasonable age for the site’s content – as though “are you under or over this age?” were insufficient – but let’s be honest, If you’re giving them you’re real name and age, they are probably not your greatest security risk. I don’t even give them a valid email address! I use something like mailinator, or a dummy email account that I never check. It’s psychegophantom@hotmail.com; go ahead, email it all you want. My kids have so many fake names, they’re no longer sure what their real names are. All I’m saying is… if a site is not storing (or I am not offering) sensitive data, it shouldn’t require another proprietary set of credentials, right? Right! If they’ve got my bank account or SS#, though, I’m willing to give a blood sample if it were possible.
So as I entertain projects that might persist a user’s non-sensitive data, I think it was my responsibility to engage a solution like OpenID. And, as a software developer, I can say that it was certainly a much easier route than developing or implementing another proprietary credential management tool. Save the few misunderstandings that could have been avoided had I just RTFM, this solution would have taken no more than 15 minutes to implement.
For an overview of OpenID, visit http://openid.net/get-an-openid/what-is-openid/
A Basic OpenID implementation in C# – Using DotNetOpenAuth
Download the .Net library at http://www.dotnetopenauth.net. You can get the source there, too, if you want an in depth understanding of the underlying mechanics.
Create a login page to guide the user through the process. An example.. http://www.jamespritz.com/login/login.aspx
I chose the OpenIdLogin control simply so I could provide common providers while still allowing the user to enter the discovery url of their preference. It also allows the page to function without javascript.
<%@ Register Assembly="DotNetOpenAuth" Namespace="DotNetOpenAuth.OpenId.RelyingParty" TagPrefix="rp" %>
<form id="login" runat="server">
<rp:OpenIdLogin ID="OpenIdLogin1" runat="server" CssClass="openid_login" RequestCountry="Request" RequestEmail="Require" RequestGender="Request" RequestNickname="Request" RequestTimeZone="Require" RememberMeVisible="False" PolicyUrl="~/PrivacyPolicy.aspx" TabIndex="1" OnLoggedIn="OpenIdLogin1_LoggedIn" OnLoggingIn="OpenIdLogin1_LoggingIn"/>
</form>
The OpenId_LogginIn event occurs before attempting to communicate with the identity provider, so you can gather information about the request before it is made.
The OpenId_LoggedIn event occurs in response to the identity provider’s action; this is where you inspect the results and determine if the provider was able to authenticate the user. You can also inspect the ClaimsResponse on form load, but this seems to flush the response cache, which will cause an error if you trap the loggedin event as well.
protected void OpenIdLogin1_LoggedIn(object sender, OpenIdEventArgs e)
{
ClaimsResponse r = e.Response.GetExtension<ClaimsResponse>();
switch (e.Response.Status)
{
case AuthenticationStatus.Authenticated:
{
//gather the user info from r
break;
}
default:
{
//handle the other cases
break;
}
}
}
That’s it! You can simply persist the user’s info in a session variable for the duration of their session. Or you can build a more sophisticated solution that persists user information and allows you to log them in automatically.