Adding OpenID authentication to your ASP.NET MVC 4 application

I am currently working on an MVC4 project that allows users to authenticate through OpenID. I don’t think I need to convince anyone about the benefits for both parties that come with that. Users don’t have to register at your site, and you have less of those tedious account maintance tasks.

Although it’s apparently coming later on as a built-in feature into the Visual Studio templates (Damien Edwards showed that stuff for Web Forms during aspConf), let me show how you can very quickly add simple OpenID support to your MVC4 application.

More after the jump.

Setting the satge

Let’s start with the basic MVC4 project, Internet template.

First of all you will need the excellent DotNetOpenAuth library, and that’s, obviously, something you should get from Nuget. After installing, you’d see a number of libraries added to your application.

Next thing to do is to grab openid-selector JS library. This can be downloaded from http://code.google.com/p/openid-selector/. Once downloaded, unzip the contents and copy all the images and CSS folders to your app’s “Content” folder. Additionally, copy openid-en.js and openid-jquery.js from the JS folder to your app’s “Scripts.” We only need that, because we will be relying on JQuery only.

This JS library will give our login page a familiar look you know for example from Stackoverflow, and would act as a ready plug and play interface for OpenID authentication.

Adding the CS and JS to the views

Since this is MVC4 we can leverage on bundles. Go to App_Start/BundleConfig.cs and add the following there:

This would allow us to easily embed the openid specific JS/CSS whereever we need them. We need a couple of more minor tweaks before we proceed. In the Scripts/openid-jquery.js change

to

so that it corresponds to our MVC4 project structure. If you are using the standard MVc4 project, go to site.css and remove padding-left and padding-right from the a tag definition, as that would ruin our OpenID layout.

Now let’s add the bundles to our view. Go to Views/Account/Login.cshtml. You can delete the existing FormsAuthentication form entirely, as we will be switching to OpenId authentication. Add our CSS bundle and in the scripts Razor section add our script bundle:

Finally, add the HTML form that will act as our OpenID gateway for our application’s users.

Our front end work is done for now, and we should be getting a nice Login page by now (which, of course, does nothing for the time being).

Implementing OpenID authentication service

Before we start the C# implementation part of this, let me briefly explain how we are going to approach the problem:

1. We will be calling the OpenID provider to authenticate our user
2. The response claim will get wrapped into a custom OpenIdUser object
3. When the user is successfully authenticated we will issue a FormsAuthentication ticket based on that OpenIdUser, this way we will be able to leverage on ASP.NET IPrincipal implementation (HttpContext.Current.User).
4. We will actually have a custom IIdentity implementation as well. This way, you could access the information stored in OpenIdUser from anywhere in the application by just typing User.Identity.OpenIdUser

The model

We will start by creating the OpenIdUser.

The model is rather simple, and has the properties you’d normally expect from the User type of model, except Password of course, which is not needed. We have two constructors, because there are two ways in which we will create this object.

First way is to takee in a string that’s been decrypted from Forms authentication ticket UserData part. This is how we will get the info of the user from the cookie and inject into HttpContext as our IIdentity (will show this later).

The second constructor takes in claims response from OpenId provider, and populates the properties based on that.

We also have a simple ToString method which we’ll use to “serialize” the object into a string and embed this data in the Forms ticket.

The service

Now let’s add the service, which will do all the heavy lifting for us.

We will start off with an interface – although it’s not necessary, it could come in handy if you wish to provide an alternative implementation later on. For example, in this particular tutorial, I will not be saving user information into our database at all – we simply use OpenID to authenticate a user. If you wish to store those OpenIDs in your user repository you might very easily do that.

Moreover, since we have an interface in place, you might want to change the implementation to not piggyback on FormsAuthentication tickets as we will do in this example, but use a completely different IPrincipal implementation.

The interface defines two methods – one to generate a request that is validatable against some openID provider and the other to get user.

Our implementation is as follows:

It’s not very complicated at all. In the constructor we instantiate an OpenIdRelyingParty, which will be our OpenID authentication mediator. When the client calls ValidateAtOpenIdProvider and passes the username to be authenticated, we set up a set of request fields (Claim, in OpenID lingo) which we’d like the OpenID provider to return – in our case Email, FullName and NickName.

Once client has validated (authenticated itself), it can request the user object. This is done by invoking the GetUser method. This method uses a couple of helpers, but the gist is that we obtain the claim through the use of OpenIdRelyingParty. This claim can the be converted into our custom user object.

Finally, the service API exposes one more method (not defined in the interface), and that’s CreateFormsAuthenticationCookie. This creates a FormsAuthentication ticket which can be sent down to the browser.

To make this all work we need one more small extension method for the IAuthenticateRequest.

Let’s see how we can now utilize this service from the MVC4 controller.

The authentication controller

Let’s modify the existing AccountController to suit our needs. We won’t need change password and create user methods at all, so you can safely delete them.

We need to make sure we have our OpenID service available, so we add an OpenIdMembershipService field and a initizalize it in the constructor.

Let’s look at the action which will be used for authentication.

If you recall, ValidateAtOpenIdProvider will return IAuthenticationRequest, which in turn exposes a property RedirectingResponse. This lets us send the user to the external page, at the OpenID provider server (i.e. Google login), where he will need to authenticate himself. Then the view re-renders, so that automatically means we have to put the rest of the login in the default GET version of the public ActionResult Login() action.

So when the view re-renders, we try to get user from our OpenID membership service. If the user is successfully returned – meaning the user has authenticated without any problems, we proceed by issuing a FormsAuthentication ticket and redirecting the user back to the original page on which his Authentication challenged was raised – that’s levering on the standard ASP.NET ReturnUrl query string.

The user should at this point see the following:

We might as well end this tutorial here. If you need very basic authentication mechanism, this should already be OK. I will take it a step further and let’s add a customized IIdentity. This would allow us to have access to our OpenIdUser anywhere within the application by calling User.Identity.

Custom IIdentity

We will implement System.Security.Principal.IIdentity interafce, and add an OpenIdUser property there.

We will inject this custom implementation of Identity into the Principal object using a custom AuthorizeAttribute. You could do that also by registering a handler for PostAuthenticateRequest in Global.asax but that’s a bit of an overkill, as it would execute numerous times, whereas the logic in the attribute will only execute once per request.

This grabs the OpenIdUser object from the FormsAuthentication ticket (or rather its UserData section) and inject it into the HTTP context. As a result, we now can go to our partial view for the login, _LoginPartial.cshtml, and replace the login section with

Now this isn’t anything spectacular yet. But we could also use our custom Identity

As you see, this way we get access to the OpenID properties anywhere we want. Remember to decorate whichever action or controller you wish to be protected by OpenID with OpenIDAuthorize i.e.

As a side note, we don’t need any implementation of logout, since the standard one included in the out of the box AccountController does that for us (it deletes the FormsAuthentication ticket).

Trying it out

Now that we have the application’s pieces in place, let’s try it. If you used the attributes like I did above, you should be challenged right away.

If you try Google, you should see this:

And then login successfully

Same with Yahoo:

Summary

In a few simple steps we have implemented OpenID authentication thanks to the very robust DotNetOpenAuth library. You could obviously take it further, as I mentioned before, perhaps store user’s accounts in some repository of yours. Either way, this should be a decent start and I hope someone someone finds it useful. Source code is below (github).

source on github