Creating a custom Login page for federated authentication with Windows Azure ACS

Windows Azure Acess Control Service (ACS) provides a way of authenticating users who need to access web applications and services without having to factor complex authentication logic into the application itself. It is surprisingly easy to create a custom login page that delegates the authentication process to an identity provider

Since we already know how to delegate the login/authentication process to an Identity Provider using Windows Azure ACS (Online Identity Management via Windows Azure ACS and Unified Identity for web apps – the easy way ), let’s see how to create a custom login page and provide users with a seamless experience in our web application.

I will use the WaadacDemo demo code as a base to extend it to host its own login page. The complete code with custom login page is here.

Windows Azure ACS is a really flexible Identity Provider. Besides the default login page, it also provides a number of ways for us to customize the login experience for our users. All the ways are found under Application Integration menu in the Login Pages section:


Once there, we have to choose the Relying Party application for which we would like customization. Now we have a number of options:


 Option 1 is the default option we were already using, it’s the ACS hosted login page. What we are interested in is Option 2 – hosting the login page ourselves.

There are two approaches here – the client side and the server side. Both rely to a JSON list of identity providers, the link to the JSON feed URL is displayed in the last text area. If you are the JavaScript/DOM guy – I highly encourage you to download the Example Login Page and play around with the client code provided. In the following lines I’ll describe how to create the Login page with server code.

As already mentioned, both approaches rely on JSON array of identity providers. Since I still don’t like dynamic, I will use a custom type on the server to deserialize my JSON array to. Here is my tiny IdentityProvider class:

Now I don’t want to reinvent the wheel, and will use a popular JSON deserializer – NewtonSoft JSON.NET. A simple WebClient call is needed to download the JSON string and pass it to the JSON deserializer:

You might already have noticed that I use the appSettings section in web.config to keep the URL of the identity providers list. A small gotcha is to explicitly set text encoding of WebClient to UTF-8, because the Live ID identity provider has a small trademark symbol (â¢) in its name and that cannot be changed. If you do not use UTF-8 encoding, you will have some strange ASCII symbols instead of ( ⢠).

What do we do with the identity providers once we have them? Well, I’ve create a BaseMaster class which all of my MasterPages will inherit.  This BaseMaster class has a property IdentityProviders:

I also keep the retrieved list in local application cache since this is something not very likely to change often. But, you should leave it for just 20 minutes in the cache to refresh it from time to time.

Now the tricky part. In order to have your own login page we have to combine the force of Forms Authentication along with Windows Identity Foundation and its WSFederatedAuthenticationModule. If you happen to use an ASP.NET MVC application, then it is fairly easy and much discussed. I suggest that you go through Dominic Bayer’s blog post on that subject (and the details). Note that now we will not mix Forms and Claims authentication. We will use claims, but will have the Forms Authentication to help us with that task.

Let’s go through the changes needed in Web.config file. First we set the passiveRedirectEnabled attribute for wsFederation to false:

Then we change the Authentication from None for Forms:

And now add some special Locations to allow all users: Styles, Login.aspx and authenticate.aspx. We need to do that to prevent the Forms Authentication to redirect requests for these URLs. Styles, of course need to be accessed for all users. Login.aspx is our custom login page, and authenticate.aspx is a custom authentication page which we will use as Return URL for our ACS configured relying party application:


Here is the code for authenticate.aspx.cs:

We check whether the request contains SignInResponseMessage which would come from ACS. If so, then everything is fine and we must instruct the FormsAuthentication that the user is logged in via the FormsAuthentication.SetAuthCookie(). If not – redirect the user to the Login page.

Finally we will create our custom login page. Just add it as a web form using Master Page. Select the Site.Master (which inherits from BaseMaster). The simplest way of showing Identity Providers I can think of is the Repeater Control:

I bind it to the list of identity providers which I got from the BaseMaster:

Let me visually summarize the process and why it works:


If a user requests protected content, the FormsAuthenticationModule kicks and redirects the user to our Login.aspx page. There we show a list of identity providers where one can authenticate. When the user authenticates successfully with the chosen IdP, a token is sent back to the Access Control Service. The ACS processes that token with the configured rules and relying party. If everything passes fine without errors, the ACS sends a new token to the relying party’s Return URL property. In our case this is http://localhost:2700/authenticate.aspx. Since we added this URI as a special location in web.confing, no FormsAuth redirects kicks here. The WsFederationAuthenticationModule intercepts the incoming token and creates the ClaimsIdentity based on that token. It also creates the FederatedAuthentication cookie, which will be used in the subsequent requests to build up the ClaimsIdentity again. Now is the moment to also instruct the FormsAuthenticationModule that the user is already authenticated, so that it doesn’t redirect to Login.aspx.

 I hope you liked it and discovered that it is easier then you thought!