29 August 2012

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:

1615-appintegration.png

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

1615-localdemo.png

 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:

1615-returnurl.png

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:

1615-summaryprocess.png

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!

 

 

Keep up to date with Simple-Talk

For more articles like this delivered fortnightly, sign up to the Simple-Talk newsletter

This post has been viewed 27211 times – thanks for reading.

  • Rate
    [Total: 22    Average: 2/5]
  • Share

Anton Staykov

View all articles by Anton Staykov

Related articles

Also in Azure

Azure SQL Data Warehouse

Azure SQL Data Warehouse is a fully-managed and scalable cloud service. It is still in preview, but solid. Not only is it compatible with several other Azure offerings, such as Machine Learning and Data Factory, but also with various existing SQL Server tools and Microsoft products. It talks Power BI. Are we now seeing the final piece of the Azure jigsaw fall into place?… Read more

Also in Cloud

In Search of the Cortana Analytics Suite

Cortana Analytics Suite is important and significant, but it is difficult to work out why or how from the existing 'information'. After more setbacks than Dr Livingstone, Bob Sheldon emerged from the jungle of marketing hyperbole triumphantly with a small diagram which explained it. Here he reveals the individual components, and finds them, in combination, to be a curiously interesting attempt to bring Big Data under contro… Read more

Also in development

Using C# to Create PowerShell Cmdlets: The Basics

Although PowerShell Cmdlets are usually written in PowerShell, there are occasions when the level of integration with existing C# or VB libraries is awkward to achieve with PowerShell. Yes, you can write Cmdlets in C# perfectly easily, but until now it has been tiresome to discover how. Now Michael Sorens shows you the simple route to writing effective C# Cmdlets.… Read more

Also in Source control

PowerShell Desired State Configuration: LCM and Push Management Model

PowerShell's Desired State Configuration (DSC) framework depends on the Local Configuration Manager (LCM) which has a central role in a DSC architecture. It runs on all nodes that have PowerShell 4.0 or above installed in order to control the execution of DSC configurations on target nodes. Nicolas Prigent illustrates the role of the LCM in the 'Push' mode of configuring nodes.… Read more
  • Azure Mobile Service – Wealth of Information to Get Starte

    […] Creating a Custom Login Page for Federated Authentication       with Windows Azure ACS by @astaykov (posted Aug 29) […]

  • Cameron

    Great read! Thanks for posting Anton.

  • Windows Azure and Cloud Computing Posts for 8/31/2012+ – Windows

    […] Creating a Custom Login Page for Federated Authentication with Windows Azure ACS by @astaykov (posted Aug 29) […]

  • Windows Azure Community News Roundup (Edition #34) – Windows Azu

    […] Creating a Custom Login Page for Federated Authentication with Windows Azure ACS by @astaykov (posted Aug 29) […]

  • Windows Azure Community News Roundup (Edition #34) – Windows Azu

    […] Creating a Custom Login Page for Federated Authentication with Windows Azure ACS by @astaykov (posted Aug 29) […]

Join Simple Talk

Join over 200,000 Microsoft professionals, and get full, free access to technical articles, our twice-monthly Simple Talk newsletter, and free SQL tools.

Sign up

See what's happening behind the scenes

Take a peek at the bowels of the ship – the lower decks – the actual servers of SQL Server Central itself.

See what's happening