Saturday, June 30, 2012

Working with Custom Identity Provider (Intuit OpenId Provider) for ACS

Before we get into the details about various ways of adding custom Identity Provider into Azure ACS, Let me give some background about OpenId and Intuit OpenId Provider Details. I will be using Intuit OpenId Provider for this demonstration.

What is OpenId?
OpenID is a decentralized authentication protocol that makes it easy for people to sign up and access web accounts, in a simple sentence it is an open standard for logging onto various web accounts with a single digital identity. 

Intuit OpenId Provider
Intuit uses OpenId Standars for Authenticating user to access any of their services across all their web sites. In fact, this can be used by any web site including Intuit partners websites to access this user information as this is decentralized and doesn't require any approval from any authority. User can freely choose his choice of provider to access any website including Intuit Provider.
Intuit Provider URL: https://openid.intuit.com/OpenId/Provider

Now let us come back to the original topic on working with Custom Identity Provider for ACS. By default Azure ACS provides Google and MS Live Id providers as Identity providers which can be used majority of the time for learning and demonstration purpose and for all the practical scenarios users has to add their own using ACS Management Service. The management service makes it possible for you to manage ACS programmatically, in fact after getting the Management Service Namespace and Access Certificates you hardly need ACS portal for any management, You can manage everything through a simple Console application.

Now let us see how to add Intuit Identity Provider using Management Service. Before we start, you need to note the ACS Management Service Namespace and Access Certificate details. By default Azure ACS gives you "ManagementClient" as Service Identity Name and also Identity Key which is generated.

Having above details from ACS portal, you can add Custom Identity Provider in two Ways:
1>Using Powershell Scripts (Which is best approach on any given Day) and
2>Pragmatically (by Writing a small C# code and executing it on your local box).

1>Using Powershell Scripts
This is very simple and easy approach, just 2 to 3 Powershell commands and we are done with adding Custom Identity Provider, Adding Identity Rule, Adding Relying Party etc.

Following command will add Intuit Identity Provider into ACS

PS C:\Users\Manj\Desktop> Add-IdentityProvider –Namespace “intuitopenid” –ManagementKey “XXXXXXXX” -Type "Manual" -Name "Intuit" -Protocol OpenId –SignInAddress “https://openid.intuit.com/OpenId/Provider"

Management key is the important one here which I first obtain with Get-AcsManagementToken, assigned it to a variable and passed it along for all subsequent commands.

 Next step will create rules that will add some claims, Other wise, ACS won’t even send a token back. Luckily, that’s just another line of PowerShell code:

 PS C:\Users\Manj\Desktop> Add-Rule -MgmtToken $mgmtToken -GroupName "Default Rule Group for Intuit" -IdentityProviderName "IntuitOpenID"

Thats it, we are ready to use ACS as Identity Federation website for Intuit OpenID Provider.

2> Programatically  (Create a Sample Console Application and write some code)
Now this has 4 steps , First one to collect the Configuration settings,  Collect details about Management service (Web Service) End Points, Implement Management Service Client and Create Open Id provider. Looks Simple right, let us see each step in detail.

Step 1>
change the App.Config file to have the following settings in your console Application.

<appSettings>
    <add key="ServiceNamespace" value="intuitopenid"/>
    <add key="AcsHostUrl" value="accesscontrol.windows.net"/>
    <add key="AcsManagementServicesRelativeUrl" value="v2/mgmt/service/"/>
    <add key="ManagementServiceIdentityName" value="ManagementClient"/>
    <add key="ManagementServiceIdentityKey" value="AddyourKeyhere"/>
    <add key="RelyingPartyName" value="Intuit Provider Sample Application"/>
    <add key="RelyingPartyRealm" value="http://localhost:62000/"/>
    <add key="ReplyTo" value="http://localhost:62000/"/>
    <add key="RuleGroupName" value="Default rule group for ASPNET Simple Forms Sample"/>
    <add key="IntuitProviderName" value="Intuit"/>
    <add key="OpenIDProviderURL" value="https://openid.intuit.com/OpenId/Provider"/>
  </appSettings>

Step 2>
Add a reference into System.Web.Extensions and Service reference into Management Service, remember the ACS Management Service URL, this should look similar to one which is in your configuration file like
https://intuitopenid.accesscontrol.windows.net/v2/mgmt/service

now your Code file should be having this declaration:
Using System.Web
.......
Using ConsoleApplication1.ServiceReference1

 Step 3>
 We need to Implement the Management Service client, following code will do this.
/// <summary>
        /// Creates and returns a ManagementService object.
        /// </summary>
        /// <returns>An instance of the ManagementService.</returns>
        internal static ManagementService CreateManagementServiceClient()
        {
            serviceNamespace = ConfigurationManager.AppSettings["ServiceNamespace"];
            acsHostUrl = ConfigurationManager.AppSettings["AcsHostUrl"];
            acsManagementServicesRelativeUrl = ConfigurationManager.AppSettings["AcsManagementServicesRelativeUrl"];
            managementServiceIdentityName = ConfigurationManager.AppSettings["ManagementServiceIdentityName"];
            managementServiceIdentityKey = ConfigurationManager.AppSettings["ManagementServiceIdentityKey"];
            string managementServiceEndpoint = String.Format(CultureInfo.InvariantCulture, "https://{0}.{1}/{2}", serviceNamespace, acsHostUrl, acsManagementServicesRelativeUrl);
            ManagementService managementService = new ManagementService(new Uri(managementServiceEndpoint));
            managementService.SendingRequest += GetTokenWithWritePermission;
            return managementService;
        }

Step 4>
 Add Piece of code to create Intuit Identity Provider to ACS and Create Rules.

string relyingPartyName = ConfigurationManager.AppSettings["RelyingPartyName"];
       string relyingPartyRealm = ConfigurationManager.AppSettings["RelyingPartyRealm"];
       string replyTo = ConfigurationManager.AppSettings["ReplyTo"];
       string intuitProviderName = ConfigurationManager.AppSettings["IntuitProviderName"];
       string openIDProviderURL = ConfigurationManager.AppSettings["OpenIDProviderURL"];
       Uri openIDProviderUri = new Uri(openIDProviderURL);
        string ruleGroupName = ConfigurationManager.AppSettings["RuleGroupName"];
        ManagementService svc = AcsManagementServiceHelper.CreateManagementServiceClient();
        svc.DeleteRelyingPartyByRealmIfExists(relyingPartyRealm);
        svc.DeleteRuleGroupByNameIfExists(ruleGroupName);
        svc.DeleteIdentityProviderIfExists(intuitProviderName);
        svc.SaveChangesBatch();
        IdentityProvider intuit = svc.CreateOpenIdIdentityProvider(intuitProviderName, openIDProviderUri);
        IdentityProvider[] associatedProviders = new[] { intuit };

        // Create the relying party. In this case, the Realm and the ReplyTo are the same address.
        RelyingParty relyingParty = svc.CreateRelyingParty(relyingPartyName, relyingPartyRealm, replyTo, RelyingPartyTokenType.SAML_2_0, false);
        svc.AssociateIdentityProvidersWithRelyingParties(associatedProviders, new[] { relyingParty });
        RuleGroup ruleGroup = svc.CreateRuleGroup(ruleGroupName);
        svc.AssignRuleGroupToRelyingParty(ruleGroup, relyingParty);

        // Create simple rules to pass through all claims from each issuer.
        foreach (IdentityProvider identityProvider in associatedProviders)
        {
            string ruleDescription = String.Format(CultureInfo.InvariantCulture, "Pass through all claims from '{0}'", identityProvider.Issuer.Name);
            svc.CreateRule(identityProvider.Issuer, null, null, null, null, ruleGroup, ruleDescription);
        }

        svc.SaveChangesBatch();
        Console.WriteLine("Intuit Provider Successfully Configured. Press ENTER to continue ...");
        Console.ReadLine();

This should add IntuitIdentityProvider into ACS now, which is ready to be used by Relaying Parties in their websites.

Now Intuit Identity Provider is ready to be consumed. In my next blog, i will demonstrate how to use this using Node.Js website.


2 comments: