Click here to monitor SSC
  • Av rating:
  • Total votes: 22
  • Total comments: 5
Anton Staykov

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

29 August 2012

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:

ACS Login Page Integration

 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:

public class IdentityProvider
        public List<string> EmailAddressSuffixes { get; set; }
        public string ImageUrl { get; set; }
        public string LoginUrl { get; set; }
        public string LogoutUrl { get; set; }
        public string Name { get; set; }

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:

private List<IdentityProvider> GetIdentityProvidersFromAcs()
        var idPsUrl = ConfigurationManager.AppSettings["IdentityProvidersUrl"];
        var webClient = new WebClient();
        webClient.Encoding = System.Text.Encoding.UTF8;
        var jsonList = webClient.DownloadString(idPsUrl);
        var acsResult = JsonConvert.DeserializeObject<List<IdentityProvider>>(jsonList);
        return acsResult;

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:

public List<IdentityProvider> IdentityProviders
            List<IdentityProvider> idPs = Cache.Get("idps") 
            as List<IdentityProvider>;
            if (idPs == null)
              idPs = this.GetIdentityProvidersFromAcs();
            return idPs;

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:

<wsFederation passiveRedirectEnabled="false"  
           requireHttps="false" />

Then we change the Authentication from None for Forms:

<authentication mode="Forms">
      <forms loginUrl="~/Login.aspx" />

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:

Edit Relying Party Application

Here is the code for authenticate.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
(HttpContext.Current.Request.Form[WSFederationConstants.Parameters.Result] != null)
           // This is a response from the ACS - you can further inspect the message if you want
                SignInResponseMessage message =
                    as SignInResponseMessage;

                FormsAuthentication.SetAuthCookie(this.User.Identity.Name, false);


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:

<h2>Choose Login Method</h2>
    <asp:Repeater runat="server" 
            <asp:HyperLink runat="server" 
                NavigateUrl='<%#DataBinder.Eval(Container.DataItem, "LoginUrl")%>' 
                Text='<%#DataBinder.Eval(Container.DataItem, "Name")%>' />
            <br />
            <hr />

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

protected void Page_Load(object sender, EventArgs e)
            this.rptIdentityProviders.DataSource = 

Let me visually summarize the process and why it works:

Unauthenticated request flow diagram

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!



Anton Staykov

Author profile:

Anton Staykov is Microsoft MVP for the Windows Azure platform, a reward which he has received 3 times already for his continuous devotion to sharing experiences with the communities worldwide. He is a firm believer that in 21st century no single internet user shall ever create new username and password to get access to a service. New business shall respect users' online privacy and let them use their existing online identities. Anton exploits the platform ever since its first public preview back in late 2008. With more than 12 years of developing experience on small and large scales he believes there is no problem that cannot be solved. Tuned on the cloud wave Anton helps smaller and larger enterprises leverage the Windows Azure platform the best way possible, following the best practices and security guidelines outlined by Microsoft. You can follow his cloud blog at and in Twitter as @astaykov. Anton is also a regular speaker at local and global conferences (including DevReach, Microsoft Developer Days, Global Windows Azure Boot Camp and others).

Search for other articles by Anton Staykov

Rate this article:   Avg rating: from a total of 22 votes.





Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.

Posted by: Azure Mobile Service – Wealth of Information to Get Starte (not signed in)
Posted on: Monday, December 3, 2012 at 8:02 AM
Message: [...] Creating a Custom Login Page for Federated Authentication       with Windows Azure ACS by @astaykov (posted Aug 29) [...]

Posted by: Cameron (not signed in)
Posted on: Monday, December 3, 2012 at 8:02 AM
Message: Great read! Thanks for posting Anton.

Posted by: Windows Azure and Cloud Computing Posts for 8/31/2012+ - Windows (not signed in)
Posted on: Monday, December 3, 2012 at 8:02 AM
Message: [...] Creating a Custom Login Page for Federated Authentication with Windows Azure ACS by @astaykov (posted Aug 29) [...]

Posted by: Windows Azure Community News Roundup (Edition #34) - Windows Azu (not signed in)
Posted on: Monday, December 3, 2012 at 8:02 AM
Message: [...] Creating a Custom Login Page for Federated Authentication with Windows Azure ACS by @astaykov (posted Aug 29) [...]

Posted by: Windows Azure Community News Roundup (Edition #34) - Windows Azu (not signed in)
Posted on: Monday, December 3, 2012 at 8:02 AM
Message: [...] Creating a Custom Login Page for Federated Authentication with Windows Azure ACS by @astaykov (posted Aug 29) [...]


Top Rated

Using Azure KeyVault with Node.js
 Some of the most intractable problems of application design are concerned with how to store credentials... Read more...

How to Build and Deploy Azure IaaS VMs with PowerShell
 The whole point of using a cloud service is to be able to use it intensively for a brief period just... Read more...

Pragmatic IoT on Azure Part 1: Introduction
 A Pragmatic Introduction to Building IoT Solutions on the Azure Platform by Rick Garibay. Rick starts... Read more...

Azure API Management Part 2: Safeguarding Your API
 Learn about how you can use Subscription Keys, OAuth 2.0 and Profiles to safeguard your APIs using... Read more...

Azure Active Directory Part 3: Developing Native Client Applications
 Rick Rainey continues his series by detailing how to integrate a native client application with Azure... Read more...

Most Viewed

Windows Azure Virtual Machine: A look at Windows Azure IaaS Offerings (Part 2)
 We continue our introduction of the Azure IaaS by discussing how images and disks are used in the Azure... Read more...

An Introduction to Windows Azure BLOB Storage
 Azure BLOB storage is persistent Cloud data storage that serves a variety of purposes. Mike Wood shows... Read more...

An Introduction to Windows Azure Table Storage
 Windows Azure Tables are intended for the storage of large amounts of schemaless data. Tables are just... Read more...

Windows Azure Management Certificates
 Although Windows Azure can be used from the portal, it comes into its own once provisioning,... Read more...

An Introduction to Windows Azure Service Bus Brokered Messaging
 As applications grow, a message queue system soon becomes the best way of achieving scalability. It is... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.