Adding Internet Identity Providers like Facebook, Google, LiveID and Yahoo to your MVC web application using Windows Azure AppFabric Access Control Service and jQuery in 3 steps

If you want to achieve a login user experience like the one shown in the following screenshot, then keep reading…

image

Windows Azure AppFabric Access Control 2.0 has been released last week after one year in the Labs environment and it was officially announced today at MIX. If you haven’t heard about it yet, here is the elevator pitch of ACS v2:

Windows Azure AppFabric Access Control Service (ACS) is a cloud-based service that provides an easy way of authenticating and authorizing users to gain access to your web applications and services while allowing the features of authentication and authorization to be factored out of your code. Instead of implementing an authentication system with user accounts that are specific to your application, you can let ACS orchestrate the authentication and much of the authorization of your users. ACS integrates with standards-based identity providers, including enterprise directories such as Active Directory, and web identities such as Windows Live ID, Google, Yahoo!, and Facebook

According to the blog published today by the AppFabric team you can use this service for free (at least throughout Jan 2012). Also the Labs environment are still available for testing purposes (not sure when they will turn this off).

We encourage you to try the new version of the service and will be offering the service at no charge during a promotion period ending January 1, 2012.

Now that we can use this for real, in this post I will show you how to create a little widget that will allow users of your website to login using social identity providers like Google, Facebook, LiveId or Yahoo. In this post I will go through the process of creating such experience for your website.

I will use an MVC Web Application, but this can be implemented in WebForms also or even WebMatrix if you understand the implementation details

Step 1. Configure Windows Azure AppFabric Access Control Service

  1. Create a new Service Namespace in portal.appfabriclabs.com or if you have an Azure subscription use the production version at windows.azure.com

    image
  2. The service namespace will be activated in a few minutes. Select it and click on Access Control Service to open the management console for that service namespace.
  3. In the management console go to Identity Providers and add Google, Yahoo and Facebook (LiveID is added by default). It’s very straightforward to do it. This is the information you have to provide for each of them. I just googled for the logos and some of them are not the best quality, so feel free to change them
  4. The next thing is to register the web application you just created in ACS. To do this, go to Relying party applications and click Add.
  5. Enter the following information
    Name: a display name for ACS
    Realm: https://localhost/<TheNameOfTheWebApp>/
    This is the logical identifier for the app. For this, we can use any valid URI (notice the I instead of L). Using the base url of your app is a good idea in case you want to have one configuration for each environment.
    Return Url: https://localhost/<TheNameOfTheWebApp>/
    This is the url where the token will be posted to. Since there will be an http module listen for any HTTP POST request coming in with a token, you can use any valid url of the app. The root is a good choice and, don’t worry, then you can redirect the user back to the original url she was browsing (in case of bookmarking).

    image
  6. Leave the other fields with the default values and click Save. You will notice that Facebook, Google, LiveID and Yahoo are checked. This means that you want to enable those identity providers for this application. If you uncheck one of those, the widget won’t show it.
    image
  7. Finally, go to the Rule Groups and click on the rule group for your web application.
    image
  8. Since each identity provider will give us different information (claims about the user), we have to generate a set of rules to passthrough that information to our application. Otherwise by default that won’t happen. To do this, click on Generate, make sure all the identity providers are checked and save. You should see a screen like this

    image
     

Step 2. Configure your application with Windows Azure AppFabric Access Control Service

  1. Now that we have configured ACS, we have to go to our application and configure it to use ACS.
  2. Create a new ASP.NET MVC Application. Use the Internet Application template to get the master page, controllers, etc.
    NOTE: I am using MVC3 with Razor but you can use any version.
  3. Before moving forward, make sure you have Windows Identity Foudnation SDK installed in your machine. Once you have it, then right click the web application and click Add STS Reference…. In the first step you will have already the right values so click Next

    image
  4. In the next step, select Use an existing STS. Enter the url of your service namespace Federation Metadata. This URL has a pattern like this:
    https://<YourServiceNamespace>.accesscontrol.appfabriclabs.com/FederationMetadata/2007-06/FederationMetadata.xml

     image
  5. In the following steps go ahead and click Next until the wizard finishes.
  6. The wizard will add a couple of http modules and a section on the web.config that will have the thumbprint of the certificate that ACS will use to sign tokens. This is the basis of the trust relationship between your app and ACS. If you change that number, it means the trust is broken.
  7. The next thing you have to do is replace the default AccountController with one that works when the authentication is outsourced of the app. Download the AccountController.cs, change the namespace to yours and replace it. Among other things, this controller will have an action called IdentityProviders that will return from ACS the list of identity providers in JSON format.

    public ActionResult IdentityProviders(string serviceNamespace, string appId)
    {
        string idpsJsonEndpoint = string.Format(IdentityProviderJsonEndpoint, serviceNamespace, appId);
        var client = new WebClient();
        var data = client.DownloadData(idpsJsonEndpoint);
    
        return Content(Encoding.UTF8.GetString(data), "application/json");
    }
    

Step 3. Using jQuery Dialog for the login box

  1. In this last step we will use the jQuery UI dialog plugin to show the list of identity providers when clicking the LogOn link. Open the LogOnPartial cshtml file

    image
  2. Replace the LogOnPartial markup with the following (or copy from here). IMPORTANT: change the service namespace and appId in the ajax call to use your settings.

    @if(Request.IsAuthenticated) {
        <text>Welcome <b>@Context.User.Identity.Name</b>!
        [ @Html.ActionLink("Log Off", "LogOff", "Account") ]</text>
    }
    else {
        <a href="#" id="logon">Log On</a>
        <div id="popup_logon">        
        </div>
        <style type="text/css">
        #popup_logon ul
        {
            list-style: none;
        }
        #popup_logon ul li
        {
             margin: 10px;
             padding: 10px
        }
        </style>
        <script type="text/javascript">    
        $("#logon").click(function() {
            $("#popup_logon").html("<p>Loading...</p>");
            $("#popup_logon").dialog({ modal: true, draggable: false, resizable: false, title: 'Select your preferred login method' });  
            $.ajax({
                url : '@Html.Raw(Url.Action("IdentityProviders", "Account", new { serviceNamespace = "YourServiceNamespace", appId = "https://localhost/<YourWebApp>/" }))',
                success : function(data){
                    dialogHtml = '<ul>';
                    for (i=0; i<data.length; i++) 
                    {
                        dialogHtml += '<li>';
                        if (data[i].ImageUrl == '') 
                        {                  
                            dialogHtml += '<a href="' + data[i].LoginUrl + '">' + data[i].Name + '</a>';
                        } else 
                        {
                            dialogHtml += '<a href="' + data[i].LoginUrl + '"><img style="border: 0px; width: 100px" src="' + data[i].ImageUrl + '" alt="' + data[i].Name + '" /></a>'; 
                        }
    
                        dialogHtml += '</li>';
                    }
    
                    dialogHtml += '</ul>';
    
                    $("#popup_logon").html(dialogHtml);                          
                }
            })
         });
    
        </script>
        
    }
  3. Include jQuery UI and the corresponding css in the Master page (Layout.cshtml)
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery-ui.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery-ui.min.js")" type="text/javascript"></script> 
    

Step 4. Try it!

  1. That’s it. Start the application and click on the Log On link. Select one of the login methods and you will get redirected to the right page. You will have to login and the provider may ask you to grant permissions to access certain information from your profile. If you click yes you will be logged in and ACS will send you a set of claims like the screen below shows.


    image

    image image
    image image



    image

I added this line in the HomeController to show all the claims:

ViewBag.Message = string.Join("<br/>", ((IClaimsIdentity)this.User.Identity).Claims.Select(c => c.ClaimType + ": " + c.Value).ToArray());

Well, it wasn’t 3 steps, but you get the point Winking smile. Now, it would be really cool to create a NuGet that will do all this automatically...

Just for future reference, these are the claims that each identity provider will return by default

Facebook

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: 619815976
http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration: 2011-04-09T21:00:01.0471518Z
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: yourfacebookemail@boo.com
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: Matias Woloski
http://www.facebook.com/claims/AccessToken: 111617558888963|2.k <stripped> 976|z_fmV<stripped>3kQuo
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: Facebook-<appid>

Google

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: https://www.google.com/accounts/o8/id?id=AIt<stripped>UoU
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: yourgooglemail@gmail.com
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: Matias Woloski
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: Google

LiveID

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: WJoV5kxtlzEbsu<stripped>mMxiMLQ=
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: uri:WindowsLiveID

Yahoo

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: https://me.yahoo.com/a/VH6mn5oV<stripped>58mGa#e7b0c
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress: youryahoomail@yahoo.com
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: Matias Woloski
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: Yahoo!

Following up

Get the code used in this post from here.

If you are interested in other features of ACS, these are some of the things you can do:

DISCLAIMER: use this at your own risk, this code is provided as-is.

blog comments powered by Disqus