• 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

    Published by on April 12th, 2011 2:43 pm under Access Control Service, Federation, Identity, Windows Identity Foundation

    9 Comments

    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.

Tags