OpenID with ASP.NET Made Simple
Implementing OpenID can be challenging, because of large number of scenarios and parties it can be used for and by. So any decent implementation includes lots of stuff you don’t particularly care about and it is hard to parse information to find exactly what you need. To save you some reading time, here how it works with ASP.NET application in the nutshell.
Create new web application project in Visual Studio 2010. It comes with Account module that let users log in and register. We want to enhance it with OpenID functionality. First, open Account/Login.aspx and add this markup right before asp:login control:
<asp:ImageButton ID="btnGoogle" runat="server" ImageUrl="~/Styles/google.png" onclick="btnGoogle_Click" />
Now Login page should look like this (you need that google.png to exist):
We also need a good library so we don’t have to do plumbing code all by hand. Most popular on .NET side seems to be dotnetopenauth.net, you can download code or binaries from website or even install it as Nuget package. I prefer to download and add single DotNetOpenAuth.dll to the project, that all you really need in most cases. Set project reference to DLL, open Account/Login.aspx.cs and add using directives:
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OpenId;
using DotNetOpenAuth.OpenId.RelyingParty;
Ready to code! Let's handle that Google image button click first, add this method to login page code behind:
protected void btnGoogle_Click(object sender, ImageClickEventArgs e)
{
using (OpenIdRelyingParty openid = new OpenIdRelyingParty())
{
var request = openid.CreateRequest("https://www.google.com/accounts/o8/id");
request.RedirectToProvider();
}
}
When user clicks Google image, we create instance of “relying party” object and call CreateRequest method passing it Google API endpoint “google.com/accounts/o8/id”. If endpoint exists and request created, we redirect it to Google for authentication. Nothing fancy, all plain and clear.
If user logged into Gmail, he is already authenticated and Google will send back response verifying user’s credentials. If not, user will be asked log into Gmail first. Then response will be send back to caller, it means our login page. We need to handle returning call on page load:
protected void Page_Load(object sender, EventArgs e)
{
var openid = new OpenIdRelyingParty();
var response = openid.GetResponse();
if (response != null && response.Status == AuthenticationStatus.Authenticated)
{
FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, false);
}
}
Again we use relying party object, this time to create response. If response is authenticated by Google – we know who user is. It does not mean user exists in our membership database, it only means that we know ID that Google assigns to this person, nothing else. What to do about it entirely up to us. We can do nothing at all and just tell forms authentication to authenticate user and redirect from login page, then only difference would be that this user is not anonymous anymore, he is authenticated. Take a look at the picture below.
It would be nice to do something useful though since we went into trouble identifying this person. At a minimum we could use some logic in our app that does things differently for authenticated users. Next step would be to save this ID so we can recognize user next time and do something about it. Even better, we can register this user with our membership so that he will become just as anyone who registered with regular account. Again, implementation details are up to you, only depend on business requirements and not related to OpenID, so we won't go there just yet.
In the next post I’ll do more real world end-to-end implementation, but before that it is important to understand basics and this stripped down version let you see how things work without any destruction. It is as simple as it gets, but it is fully functional OpenID sign-in for a single provider, and you can play with code (VS solution attached) if you want understand it better.