Exercise 1: Use ACS to Federate with Multiple Business Identity Providers

In this exercise you are going to outsource to ACS the authentication part of a newly created web site. You will configure ACS to delegate authentication to two different business identity providers, using both the portal and the management API. If you already went through the introductory hands-on lab, you will discover that the steps you need to follow are consistent with what you had to do for using web identity providers.

In a real-life solution, the business identity providers would expose their authentication functions using Active Directory Federation Services 2 or similar packaged software offering an STS. In order to keep the system requirements simple for the lab, here you will be using a utility which runs on the local machine and simulates a proper identity provider. The steps you need to configure ACS are, however, absolutely the same as if you’d be using a real system.

Note:
You require an AppFabric Service Namespace to complete this exercise. If you have not already done so, complete the section Getting Started: Creating a Service Namespace.

Task 1 – Creating the Initial Solution

  1. Open Microsoft Visual Studio 2010 with administrator privileges. From Start | All Programs | Microsoft Visual Studio 2010, right-click Microsoft Visual Studio 2010 and select Run as administrator.
  2. Open the WebSiteAdvancedACS.sln empty solution file located inside the Source\Ex01- ACSLabsV2Federation\Begin folder of this Lab.
  3. Create a new empty website. From File | Add | New Web Site, select Visual C# in the Installed Templates section and then click ASP.NET Web Site. Change the Web location field to use HTTP and set the value to https://localhost/WebSiteAdvancedACS.

    Figure 1

    Add New Web Site

  4. In the Solution Explorer delete the following folders from the web site:
    • Account
    • Scripts
  5. And the following files:

    • About.aspx
    • Global.asax

    Figure 2

    Solution Explorer

  6. Open the Site.master file and remove the DIV element with class named “loginDisplay” and the NavigationMenu menu control.

    ASP.NET

    <div class="page"> <div class="header"> <div class="title"> <h1> My ASP.NET Application </h1> </div> <div class="loginDisplay"> <asp:LoginView ID="HeadLoginView" runat="server" EnableViewState="false"> <AnonymousTemplate> [ <a href="~/Account/Login.aspx" ID="HeadLoginStatus" runat="server">Log In</a> ] </AnonymousTemplate> <LoggedInTemplate> Welcome <span class="bold"><asp:LoginName ID="HeadLoginName" runat="server" /></span>! [ <asp:LoginStatus ID="HeadLoginStatus" runat="server" LogoutAction="Redirect" LogoutText="Log Out" LogoutPageUrl="~/"/> ] </LoggedInTemplate> </asp:LoginView> </div> <div class="clear hideSkiplink"> <asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal"> <Items> <asp:MenuItem NavigateUrl="~/Default.aspx" Text="Home"/> <asp:MenuItem NavigateUrl="~/About.aspx" Text="About"/> </Items> </asp:Menu> </div> </div>

  7. Open the Web.config file and remove the following sections:

    • connectionStrings
    • system.web/authentication
    • system.web/membership
    • system.web/profile
    • system.web/roleManager

    The Web.config should look like the code bellow.

    XML

    <?xml version="1.0"?> <!-- For more information on how to configure your ASP.NET application, please visit https://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <system.web> <compilation debug="false" targetFramework="4.0" /> </system.web> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration>
    Note:
    Note: all this cleanup is not strictly necessary, but it helps to keep things simple and highlight the code that will be required for integrating with ACS.

  8. Press F5 to run the Web site and ensure us that it works as expected. If an alert about “Debugging Not Enabled” appears, select “Modify the Web.config file to enable debugging” and click OK.

    Figure 3

    “Debugger Not Enabled” Alert

    Figure 4

    Running the Application

  9. Close the browser.

Task 2 – Configure one entry for the application in the Access Control Service with the AppFabric portal

Before being able to use ACS for offloading authentication, you need to let ACS know about your application. You can easily do this by working on your AppFabric project and namespace via management portal.

  1. Navigate to https://windows.azure.com/. You will be prompted for your Windows Live ID credentials if you are not already signed in.
  2. Go to Service Bus, Access Control & Caching, located under the navigation pane.
  3. Select the Access Control item on the Navigation pane.
  4. With the Namespace selected, click the Access Control Service – Manage button on the top toolbar. Make sure that appservices.azure.com is allowed to show popups in your browser.

    Figure 5

    Click the Access Control Service – Manage button

  5. This launches (in another browser window or tab) the Access Control Service Management Portal, shown in the figure below.

    Figure 6

    Access Control Service Management Portal

    Note:
    The Management Portal offers you a global view of all the settings you can change in ACS. In this task we want to add a new application: in identity jargon, you use the expression “Relying Party” for referring to an application.

  6. Click the Relying Party Applications link on the navigation menu in order to register your Web site with ACS. ”Relying Party” is identity speak for application, the entity which consumes identities, whereas as you already guessed “Identity Provider” indicates one entity which stores identities and is capable of authenticating users.

    Figure 7

    Identity Providers configured

  7. Click the Add link on top of the Relying Party Applications table and fill the form with the following values:

    • Name: WebSiteAdvancedACS
    • Mode: Enter settings manually
    • Realm: https://localhost/WebSiteAdvancedACS/
    • Return URL: https://localhost/WebSiteAdvancedACS/Default.aspx
    • Error URL: leave the field empty
    • Token format: SAML 1.1
    • Token encryption policy: None
    • Token lifetime (secs): 600
    • Identity providers: leave the default (Windows Live ID)
    • Rule groups: Create New Rule Group
    • Token signing: Use service namespace certificate (standard)
    Note:
    Those values describe everything ACS needs to know for handling authentication for your application. We’ll get in more details later: here we will just say that upon successful authentication ACS sends back to the application a security token (an artifact such as an XML fragment, a piece of binary or json code, anything as long as it is digitally signed) as proof that successful authentication actually took place. In order to do so, ACS needs to know the address of the application to which the token should be returned to, the desired characteristics of the token it has to create, and so on.

    In this lab we will give you the instructions for getting the scenario up and running, but we will not go in great details about the underlying security mechanisms and protocols. If you want to know more about what happens behind the scenes, please refer to the presentations and videos section of the training kit.

    Figure 8

    Add Relying Party Application

    Note:
    The Realmfield MUST have the trailing slash or the authentication operations will fail.

  8. Click the Save button.
  9. Under the Development section of the navigation menu, click the Application Integration link. Here there are various URIs that come in handy when configuring your application to take advantage of ACS.
  10. Go to Endpoint Reference section and copy the value for WS-Federation Metadata. You will discover what that is and what it is used for right at the beginning of the next step.

    Figure 9

    Copying WS-Federation Metadata

Task 3 – Configuring a Website to Accept Tokens from Access Control Service

For a web application, outsourcing authentication ACS means forwarding every request from unauthenticated users to ACS. ACS will do something for making authentication happen (details below), and as we have seen above the result will be a security token. All those redirects are usually done according to specific protocols, which are platform and vendor-independent.

ACS can emit different token types on various protocols. For Web sites, the default protocol is WS-Federation. There’s no need to go in the fine details: suffice to say that WS-Federation is a protocol that is natively understood by Windows Identity Foundation (WIF), an extension to the .NET framework that allows you to easily outsource application authentication to tokens sources such as the ACS itself. In particular, WIF extends Visual Studio with a wizard which can automatically configure your application to outsource authentication without requiring you to write a single line of code. All it needs is the address of a machine-readable description of the token source to be used: in our case, that description is the WS-Federation Metadata address you saved at the end of Task 3. In identity parlance, a service which emits security token is called a Security Token Service (STS).

In this task you will use the WIF wizard to outsource authentication to ACS.

  1. Back to Visual Studio, right-click the WebSiteAdvancedACS project and select Add STS reference.
  2. When the Federation Utility window shows up, perform the following tasks for each step in the wizard.
    1. On the Welcome page click Next to continue using the pre-populated fields.

      Figure 10

      Federation Utility Wizard

    2. On the Security Token Service page select Use an existing STS, and paste the endpoint taken from Task 2 – Step 10 in the Use an existing STS field and click Next. That endpoint serves the document describing the WS-Federation STS that ACS exposes a in your AppFabric namespace.

      Figure 11

      Use an Existing STS option

    3. On the STS signing certificate chain validation error page select Disable certificate chain validation and click Next.

      Figure 12

      Disable certificate chain validation option

    4. On the Security token encryption page select No encryption and click Next.

      Figure 13

      Security Token encryption

    5. On the Offered claims page click Next.

      Figure 14

      Offered Claims

      Note:
      The WS-Federation Metadata can contain descriptions of the claims that the endpoint offers. The wizard shows those to you so that you will know what information about incoming users you will be able to process in your application. In this case ACS declares that it can release information about which identity provider was actually used for authentication and a user identifier.

    6. On the Summary page review the changes that will be made and click Finish.

Task 4 – Use the ACS Management Portal to Trust a Business Identity Provider and Process User Attributes via Claims Mapping Rules

Figure 15

ACS does not directly authenticate users, but it brokers authentication between your application and multiple providers. The picture shows a simplified authentication flow, which will be described in the following tasks

ACS does not directly authenticate users: in the most common cases it does not maintain credentials such as username and password, but it rather brokers authentication between your application and other providers. Let’s say that you are developing an inventory application for your warehouse, and two partner companies need to have access to it in order to sell your goods. You want the employees of those two partners to have authenticated access to your application, but you don’t want to manage their identities. Here’s where ACS comes to the rescue: assuming that those companies expose their own STSs as well, ACS will simply take care to redirect unauthenticated requests to one or the other, process the resulting token and send back a new authentication token to your application. That way, users never have to disclose their credentials outside of their own infrastructure and you never have to manage credentials you don’t own. Organizations which expose via STS their capability of authenticating users are called Identity Providers (IP for short).

In this task you will use the portal for configuring ACS to accept users from the first of two identity providers.

  1. Back to the browser, click the Identity Providers link in the Trust Relationships section of the menu. The main area of the management portal will display a page which helps you to manage the identity providers from where your application users will come from.

    Figure 16

    Identity Providers

  2. Click the Add link above the Identity Providers table, choose WS-Federation identity provider and click Next.

    Figure 17

    Adding Identity Provider

    Note:
    ACS is able to broker authentication with many different types of identity providers. Web IPs such as Windows Live ID, Google, Yahoo and Facebook are all services available on the public internet, defined by the address of their STS (or equivalent), the set of attributes (claims) they share about their users and the authentication protocol they use.

    Business IPs, conversely, behaves in a slightly different way. Every company will have its own STS address, will share different claims about their users, and so on. In ACS you can add multiple business IPs: one of the advantages of ACS is exactly that it can help you to manage many trust relationship without burdening your application code.

    As of today, the protocol that ACS uses for handing business IPs for web applications is WS-Federation. On the Windows platform the standard way of exposing an STS is using Active Directory Federation Services 2.0, which is why the “Add” button for adding a business IP is labeled as in Figure 22. However any WS-Federation STS should work, even from non-Windows platform (WS-Federation is an open, vendor-independent standard).

  3. Complete the form with the following information:

    • Identity Provider Settings
      • Display Name: SelfSTS1
      • WS-Federation metadata:Select File, and then Browse the fileSource\Assets\SelfSTS1\FederationMetada.xml in the lab’s folder
    • Login Page Settings
      • Login link text: SelfSTS1
      • Image URL: (leave blank)
      • Email domain name(s): (leave blank)
    • Used by
      • Relying party applications: WebSiteAdvancedACS

    Figure 18

    Filling information about the first business IP in the ACS portal

    Note:
    The form you just filled is the functional equivalent of the wizard you ran on your application back on task 3, this time applied to ACS. The wizard configured the application to redirect unauthenticated requests to the ACS and accept the resulting tokens as proof of authentication; this form is configuring ACS to redirect unauthenticated requests to the first business IP and accept the tokens it emits as authentication proofs.

    Below you will learn more details about the STS we are using for simulating business IPs in this lab.

  4. Click the Save button.
  5. In the Trust Relationships section of the navigation menu, click the Rule Groups link in order to select the default rule group for your application.

    Figure 19

    The current rule groups list contains just the default rule group

    Note:
    Note: A very important aspect of security tokens is that they contain claims, attributes describing the authenticated user as asserted by the originating STS. The claims, which can be pretty much anything about the user (name, email, group memberships, privileges, spending limits and so on), provide key information which drive the authentication and authorization process. ACS provides a rule engine which can process the claims received in the incoming token, and include the resulting transformed claims in the token sent back to the application. Often the claims in the output token will be simple pass-through of the values received from the IP, but in many cases ACS will perform important transformations such as assigning application-specific roles to the incoming user on the basis of, for example, their group memberships in their originating organization. In the steps below you will learn how to set up some simple transformation rules.

  6. Click Default Rule Group forWebsiteAdvacedACS.
  7. Click the Add link.

    Figure 20

    Add Rule link

  8. Complete the rule with the following values:

    • If …
      • Claim issuer: Select Identity Provider, and then select SelfSTS1 in the dropdown
      • (And) Input claim type: Select Select Type, and then select https://selfsts1.com/claims/name value in the dropdown
      • (And) Input claim value: Select Any
    • Then
      • Output claim type: Select Select type, and then select shttps://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
      • Output claim value: Select Pass through input claim value
    • Rule information
      • Description: Pass through “name” claim from SelfSTS1 as “name” 

    Figure 21

    Adding name pass through Rule

  9. Click the Save button.
  10. Repeat the previous steps to add the following 3 additional rules:

    Rule 2

    Claim Issuer

    Identity Provider - SelfSTS1

    (And) Input claim type

    Select Type - https://selfsts1.com/claims/emailaddress

    (And) Input claim value

    Any

    Output claim type

    Select Type -

    https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress

    Output claim value

    Pass through input claim value

    Description

    Pass through “emailaddress” claim from SelfSTS1 as “emailaddress”

    Rule 3

    Claim Issuer

    Identity Provider - SelfSTS1

    (And) Input claim type

    Select Type - https://selfsts1.com/claims/Group

    (And) Input claim value

    Enter value - Administrators 

    Output claim type

    Enter Type -

    https://schemas.xmlsoap.org/ws/2005/05/identity/claims/role

    Output claim value

    Enter Value- Gold

    Description

    Map Gold Rule

    Rule 4

    Claim Issuer

    Identity Provider - SelfSTS1

    (And) Input claim type

    Select Type - https://selfsts1.com/claims/Group

    (And) Input claim value

    Enter value - Users

    Output claim type

    Enter Type -

    https://schemas.xmlsoap.org/ws/2005/05/identity/claims/role

    Output claim value

    Enter Value - Silver

    Description

    Map Silver Rule

    Note:
     The first three rules you have added just pass though the name, group and email claims. Rule #3 and #4 map the group claim from SelfSTS1 the business IP to a role claim in ACS: Administrators and Users roles are map to Gold and Silver roles respectively. This is a great way of keeping your application code untainted from organization-specific considerations. Your application is just concerned about if the current user is silver or gold and enforces access rights accordingly. If the business aspects of the partnership changes, and from now on both Users and Administrator roles should now be awarded the Gold role, all you need to do is change rule 4: there is no need to touch the application code.

  11. In the Edit Rule Group page, verify the rules you have just created and click the Save button.

    Figure 22

    Saving group rules

  12. You have completed the entire configuration for the SelfSTS1 first business IP in ACS and setup your web site to trust ACS. Now you will verify its behavior by running the SelfSTS1. It’s time to verify that everything works as expected. To do this, execute the SelfSTS.exe file located in %labPath%\Source\Assets\SelfSTS1

    Note:
    In realistic settings, the business IP would expose its STS via ADFS2.0. However that would require quite a lot of infrastructure, including Active Directory and a Windows Server machine on which to turn on the necessary server role. However we want you to be able to experiment with this scenario even if all you have available is a standalone PC. To that purpose this hands-on lab uses SelfSTS, a simple utility which exposes a minimal WS-Federation STS endpoint. SelfSTS is just a Windows Forms application, which does not even require a setup and can run on any system where the WIF runtime is available. SelfSTS can be used as a test STS when developing web sites secured with Windows Identity Foundation. You can find more information in SelfSTS MSDN code page.

    All the tasks you are required to perform on ACS as application developer in order to configure a business IP are precisely the same you would do if instead of SelfSTS you would be using ADFS2.0.

    Figure 23

    The SelfSTS utility is here used for simulating the first business IP in the scenario

  13. Click the Start button: the SelfSTS endpoint will start listening for requests on the indicated port.

    Figure 24

    The SelfSTS is now listening for requests on the specified local port

  14. Back to the browser, click the Relying Party Applications link under the Trust Relationships section.
  15. Click on WebSiteAdvancedACS Relying Party.

    Figure 25

    The WebSiteAdvancedACS Relying Party configured in ACS

  16. In the Edit Relying Party Application page uncheck the Windows Live ID option into the Identity providers list, and click Save.

    Figure 26

    Removing Windows Live ID Identity Provider

    Note:
    Windows Live ID is the IP that ACS adds as the initial choice when you create a Relying Party. For development purposes it is a reasonable default, as it is the only IP for which it is certain that the developer has a relationship with (a Windows Live ID account is needed for signing up for ACS labs and creating an AppFabric project). However in this scenario we are only interested in handling identities from two specific business IPs, hence we are deselecting it.

    It is interested to notice that if we’d wish to address scenarios in which users can come both from web IPs (Windows Live ID, Facebook, Google, Yahoo) and business IPs ACS would easily handle that.

  17. Back to Visual Studio, press F5 to run the Web site.
  18. The relying party application (https://localhost/WebSiteAdvancedACS/)will redirect to the Access Control Service to authenticate.
  19. Access Control sent to our application the claims it was expecting and we are now authenticated.

    Figure 27

    User Authenticated

    Note:
    If you carefully observe the address bar in your browser as it opens the application, you can see the how the entire redirect sequence takes place: first the Web Site, then the STS, and back to the Web site. If you want to see the flow in more details, you can take advantage of utilities such as Fiddler or the Internet Explorer 9 traffic capture utility.

    Note:
    In order to keep this hands-on lab simple, we didn’t add any code to the Web site which would take advantage of the incoming claims (i.e. giving access to a certain page to gold users but not to others). WIF makes it very easy: if you are interested in learning how to leverage the incoming claims in your application access strategy, please refer to the WIF hands-on labs in this training kit.

  20. Close the browser.

Task 5 – Use the ACS Management API to Trust a Second Business Identity Provider and Create Claims Mapping Rules.

The ACS Management portal is very convenient for managing trust relationships and transformation rules. However, there are scenarios in which an interactive approach is not feasible. For example, you may need to automate the onboarding of a new IP as part of an existing batch process, or change access rules in response to programmatic events. For those cases, ACS offers an exhaustive OData based API which allows you to change all the settings you can work on with the portal, and more. The next task will give you a taste of what you can do with the management API: you will add a second business IP, simulated by another SelfSTS instance, and configure the associated claims transformation rules all via API.

  1. Back to the browser, click the Management service link under the Administration section of the menu.
  2. On the Management Service Accounts section of the Management Service page, click the ManagementClient link.

    Figure 28

    Selecting ManagementClient

  3. In the Credentials section, click the Password link.

    Figure 29

    Access Control Management Service Identity Password.

    Note:
    all calls to the management API are authenticated, of course. You need to use the credentials defined in ACS for this namespace.

  4. Copy the value of the Password field into a Notepad, as you will use it in the following steps, and then click Cancel.

    Figure 30

    Copying the management key

  5. Back to Visual Studio, add the ManagementServiceProject project. To do this, right-click the WebSiteAdvancedACS solution and select Add | Existing Project
  6. In the Add Existing Project dialog, select the ManagementServiceProject.csproj file under the Assets\ManagementService\ folder for this lab and click Open.

    Figure 31

    Adding the ManagementServiceProject

  7. In the ManagementServiceProject, open the ManagementServiceHelper.cs file.
  8. Update the following values. Change the {yourManagementServiceKey} placeholder with the password copied in notepad. Change the {youServiceNamespace} placeholder with your ServiceNamespace and save the file.

    C#

    static string serviceIdentityUsernameForManagement = "ManagementClient"; static string serviceIdentityPasswordForManagement = "{yourManagementServiceKey}"; static string serviceNamespace = "{yourServiceNamespace}"; static string acsHostName = "accesscontrol.windows.net";

  9. Add a new console application project named IdentityProviderSetup. To do this, right-click the WebSiteAdvancedACS solution and select Add | New Project. Then choose the Console Application template, update the name to IdentityProviderSetup and click OK.

    Figure 32

    Creating a new Console Application

  10. Right-click the IdentityProviderSetup project and select Properties.
  11. In the Application tab, update the Target Framework to .Net Framework 4. In the Target Framework change message dialog, click Yes to reload the project.

    Figure 33

    Updating the project to target .Net Framework 4

  12. Create a new folder named Resources. To do this, right-click the IdentityProviderSetup project, and click Add | New folder. Name the new folder Resources.
  13. Add the SelfSTS.cer file located in Assets\SelfSTS2\ in the folder you just created.

    Figure 34

    Adding the Certificate for the second Identity Provider

    Note:
    as mentioned, tokens are digitally signed. In order to trust an IP, ACS needs to know which key should be used for verifying this specific signature. Here we are preparing SelfSTS.cer, the key that ACS should use for verifying tokens coming from SelfSTS, to be uploaded as part of our trust relationship creation.

  14. Right click Resources\SelfSTS.cer and on the properties check that Copy to Output Directory is Copy always.

    Figure 35

    Configuring copy always on the Certificate file

  15. In the IdentityProviderSetup project add a reference to Microsoft.IdentityModel, System.Data.Services.Client assemblies and to the ManagementServiceProject project.
  16. Open Program.cs and add the following bolded using statements.

    (Code Snippet – ACS Labs Federation Lab - Ex01 – Task 5 – Using Statements - C#)

    C#

    using System;
    FakePre-c065e67d8ba34b29b752cf3c4b00f080-2407535935c64632a9b8918ed208fe09FakePre-341497d95707463fb64f05af780a8cc5-fc6a293e29834805a1d6359ea6aeb94cFakePre-3e9c896c04144c67a1a3f0f1dd1821be-8508e4daab5f4674b375a0e21d877459using System.Data.Services.Client; using System.IO; using ACS.Management; using Common.ACS.Management;

  17. Add the following internal class in Program.cs file.

    (Code Snippet – ACS Labs Federation Lab - Ex01 – Task 5 – RuleTypes Class - C#)

    C#

    ...
    FakePre-ac6293d96d3248ac9ddca3ab8c24f28b-fe628b0a662b437aa559a7879222beaaFakePre-718cb5f358bd4cd3bee8ce0b29a382b4-db9cc5d060f84ab892c813e3e964737e internal class RuleTypes { public const string Simple = "Simple"; public const string Passthrough = "Passthrough"; }FakePre-348ce9975ba44e97a379cf50a6ed19eb-581ebdf46f5a4e2785255d502737b60c

  18. To create a new Identity Provider add the following method to the Program.cs file inside the Program class.

    (Code Snippet – ACS Labs Federation Lab - Ex01 – Task 5 – CreateIdpManually Method - C#)

    C#

    /// <summary> /// Add an Identity Provider /// </summary> private static Issuer CreateIdpManually(DateTime startDate, DateTime endDate, ManagementService svc0, string idpName, string idpDisplayName, string idpAddress, string idpKeyDisplayName) { var issuer = new Issuer { Name = idpName }; // Check the Issuer does not exist previouly (if it exists, delete it) var oldIssuer = svc0.Issuers.Where(ip => ip.Name == issuer.Name).FirstOrDefault(); if (oldIssuer != null) { svc0.DeleteObject(oldIssuer); svc0.SaveChanges(); } // Add Issuer svc0.AddToIssuers(issuer); svc0.SaveChanges(SaveChangesOptions.Batch); Console.WriteLine("Info: Issuer created: {0}", idpName); var idp = new IdentityProvider { DisplayName = idpDisplayName, LoginLinkName = idpDisplayName, WebSSOProtocolType = "WsFederation", IssuerId = issuer.Id }; // Check the IP does not exist previouly (if it exists, delete it) var oldIdentityProvider = svc0.IdentityProviders.Where(ip => ip.DisplayName == idp.DisplayName).FirstOrDefault(); if (oldIdentityProvider != null) { svc0.DeleteObject(oldIdentityProvider); svc0.SaveChanges(); } // Add the new IP to ACS svc0.AddObject("IdentityProviders", idp); //Console.WriteLine("Info: Identity Provider created: {0}", idp.Name); Console.WriteLine("Info: Identity Provider created: {0}", idp.DisplayName); // Identity provider public key to verify the signature var cert = File.ReadAllBytes(@"Resources\SelfSTS.cer"); var key = new IdentityProviderKey { IdentityProvider = idp, DisplayName = idpKeyDisplayName, EndDate = endDate, StartDate = startDate, Type = "X509Certificate", Usage = "Signing", Value = cert }; svc0.AddRelatedObject(idp, "IdentityProviderKeys", key); svc0.SaveChanges(SaveChangesOptions.Batch); Console.WriteLine("Info: Identity Provider Key added: {0}", idpKeyDisplayName); // WS-Federation sign-in URL var idpaSignIn = new IdentityProviderAddress { IdentityProviderId = idp.Id, EndpointType = "SignIn", Address = idpAddress }; svc0.AddRelatedObject(idp, "IdentityProviderAddresses", idpaSignIn); svc0.SaveChanges(SaveChangesOptions.Batch); Console.WriteLine("Info: Identity Provider Address added: {0}", idpAddress); string labRelyingPartyName = "WebSiteAdvancedACS"; //Relying Party related to the Identity Provider foreach (var existingRelyingParty in svc0.RelyingParties) { var rpid = new RelyingPartyIdentityProvider { IdentityProviderId = idp.Id, RelyingPartyId = existingRelyingParty.Id }; existingRelyingParty.RelyingPartyIdentityProviders.Add(rpid); idp.RelyingPartyIdentityProviders.Add(rpid); svc0.AddToRelyingPartyIdentityProviders(rpid); } svc0.SaveChanges(SaveChangesOptions.Batch); Console.WriteLine("Info: Relying Party added to Identity Provider: {0}", labRelyingPartyName); return issuer; }
    FakePre-8e44f5d2cc564b3e8cf62fc493306efe-45fdaaf786594b089c3f13b846b6aa70FakePre-de4c69c3e9b349009e3d0b237bd8f401-de1e1824304e46cc98b661a0e2df7520FakePre-3b0c4b60ff7843908a96ac3fa1a4cc95-70cce54275c14481833c0b915ffc14d9FakePre-333c0055010949dfb663cf31eca15d5e-bcc4d3a8ff6245af8414e8a83390111dFakePre-78f2e3ef6c444f18b7ce84e1aa505e58-ad9ef6b0c53e4710b9591ed4ef413c4eFakePre-e21586242f5e4e0e82265843a48991f7-8fd83f85fe26420680e11dd624fdd49fFakePre-0f347360a842497e99a304223d2a3ca6-bb4e139c3561440faf0606fd2285959aFakePre-89509023dae24db9a2a992b14464288b-1afef6a095054870b4224378c62458d8FakePre-af91b9459b304acb82f38ba206a9bd0a-90c0240c11094fc3af10eac7e2412f4fFakePre-705419750c6c425595de347fc714e258-95f2e0bf32314ad3945bce60116ee4edFakePre-b0ff10dd7cf8497a8d9477d623715aa0-3ae34f20d89747fd9e013ab238bce22eFakePre-180228f202f6437aa1d8af49a4b528e2-b0841daa85a04ee3914adb60b417b551FakePre-f18f2a9c702d47fdb40ffd320d2711cd-a8c99828deaa4083a7eb4f520060319cFakePre-cac4615a43d5466a84e7dcded7a984af-c936de3ea86b45e79412c0f66fad3e09
    
    Note:
    this is quite a lot of code, but if you spend few moments looking at it, you’ll discover that it is very straightforward: it just provides the same info you’d add via portal UI when adding a new business identity provider and does some housekeeping with the collections.

  19. To create new Rules to an existing Rule Group add the following method inside the Program class.

    (Code Snippet – ACS Labs Federation Lab - Ex01 – Task 5 – AddRulesToRuleGroup Method - C#)

    C#

    /// <summary> /// Add the Rules into a Rule Group. /// </summary> private static void AddRulesToRuleGroup(string ruleGroupName, string issuerName) { ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient(); RuleGroup rg = svc.RuleGroups.AddQueryOption("$filter", "Name eq '" + ruleGroupName + "'").FirstOrDefault(); Issuer issuer = svc.Issuers.Where(i => i.Name == issuerName).ToArray()[0]; Rule namePassthroughRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, //InputClaimIssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/nome", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", RuleGroup = rg, //RuleType = RuleTypes.Passthrough, Description = "Passthrough \"nome\" claim from SelfSTS2 as \"name\"" }; svc.AddRelatedObject(rg, "Rules", namePassthroughRule); Rule emailPassthroughRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/postaelettronica", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", RuleGroup = rg, Description = "Passthrough \"postaelettronica\" claim from SelfSTS2 as \"emailaddress\"" }; svc.AddRelatedObject(rg, "Rules", emailPassthroughRule); Rule goldenRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/gruppo", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/role", OutputClaimValue = "Gold", RuleGroup = rg, Description = "Map Gold Role SelfSTS2" }; svc.AddRelatedObject(rg, "Rules", goldenRule); Rule silverRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/gruppo", InputClaimValue = "Utenti", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/role", OutputClaimValue = "Silver", RuleGroup = rg, Description = "Map Silver Role SelfSTS2" }; svc.AddRelatedObject(rg, "Rules", silverRule); svc.SaveChanges(SaveChangesOptions.Batch); Console.WriteLine(); Console.WriteLine("-----------------------------------"); Console.WriteLine("Info: Passthrough Rules:"); Console.WriteLine("Info: Passthrough Name Rule created: {0}", namePassthroughRule.Description); Console.WriteLine("Info: Passthrough Email Rule created: {0}", emailPassthroughRule.Description); Console.WriteLine(); Console.WriteLine("-----------------------------------"); Console.WriteLine("Info: Roles Rules:"); Console.WriteLine("Info: Golden Rule created: {0}", goldenRule.Description); Console.WriteLine("Info: Silver Rule created: {0}", silverRule.Description); }
    FakePre-f2352369c0b84f6f94ba6eab7325b7e5-6f224c2f2f394dbfbd0613b0837fa9beFakePre-be2418591a684769930f581236cdecb9-50184030e7f74a1bad3876b33389b390FakePre-6153b3b646964f7aaa14710b9eb2acc4-aab14c879e4f4dde9791cc5236c0d206FakePre-9ae38eb5c9c04c45ac606a75bd6b2b93-689929d1b9a0448cbfb93264fcc6bc04/// <summary> /// Add the Rules into a Rule Group. /// </summary> private static void AddRulesToRuleGroup(string ruleGroupName, string issuerName) { ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient(); RuleGroup rg = svc.RuleGroups.AddQueryOption("$filter", "Name eq '" + ruleGroupName + "'").FirstOrDefault(); Issuer issuer = svc.Issuers.Where(i => i.Name == issuerName).ToArray()[0]; Rule namePassthroughRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, //InputClaimIssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/nome", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", RuleGroup = rg, //RuleType = RuleTypes.Passthrough, Description = "Passthrough \"nome\" claim from SelfSTS2 as \"name\"" }; svc.AddRelatedObject(rg, "Rules", namePassthroughRule); Rule emailPassthroughRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/postaelettronica", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", RuleGroup = rg, Description = "Passthrough \"postaelettronica\" claim from SelfSTS2 as \"emailaddress\"" }; svc.AddRelatedObject(rg, "Rules", emailPassthroughRule); Rule goldenRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/gruppo", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/role", OutputClaimValue = "Gold", RuleGroup = rg, Description = "Map Gold Role SelfSTS2" }; svc.AddRelatedObject(rg, "Rules", goldenRule); Rule silverRule = new Rule() { Issuer = issuer, IssuerId = issuer.Id, InputClaimType = "https://www.theselfsts2.net/claims/gruppo", InputClaimValue = "Utenti", OutputClaimType = "https://schemas.xmlsoap.org/ws/2005/05/identity/claims/role", OutputClaimValue = "Silver", RuleGroup = rg, Description = "Map Silver Role SelfSTS2" }; svc.AddRelatedObject(rg, "Rules", silverRule); svc.SaveChanges(SaveChangesOptions.Batch); Console.WriteLine(); Console.WriteLine("-----------------------------------"); Console.WriteLine("Info: Passthrough Rules:"); Console.WriteLine("Info: Passthrough Name Rule created: {0}", namePassthroughRule.Description); Console.WriteLine("Info: Passthrough Email Rule created: {0}", emailPassthroughRule.Description); Console.WriteLine(); Console.WriteLine("-----------------------------------"); Console.WriteLine("Info: Roles Rules:"); Console.WriteLine("Info: Golden Rule created: {0}", goldenRule.Description); Console.WriteLine("Info: Silver Rule created: {0}", silverRule.Description); }FakePre-aa59f4a8023544f8911b53f4c4a7827b-da556715e5994276be85d3690aabb007FakePre-de59d76547a84aeca34e4f790ad80bde-4d6a771e511146a2b554dfd873919987FakePre-6d5e44f80a5b43ebb1f8f0392ae754e9-5d86db7b5b3347ce9795156e1c2c5fa7
    
    Note:
    Once again, it seems a lot of code but in fact it is roughly proportional to the data we are providing.

    If you observe the code above, you will notice that the claim types emitted by the second business identity provider are different: in this specific case, they are in Italian language. This is a typical case in which, without an intermediary such as ACS to decouple your application from the identity providers, you’d have to write specific code in order to accommodate the differences between how different partners manage and represent their users’ information.

    Using ACS allows you to write rules that will process the incoming claims, extract the information you need and create a normalized token which has consistent format regardless of the original data it was created from. Your application just needs to care about if the current user is gold or silver, and needn’t worry about the difference between “Amministratori” and “Administrators”.

  20. Now add the following method, which uses the previously created methods to create an Identity Provider with corresponding rules.

    (Code Snippet – ACS Labs Federation Lab - Ex01 – Task 5 – CreateIdentityProviderWithRules Method - C#)

    C#

    private static void CreateIdentityProviderWithRules() { ManagementService svc = ManagementServiceHelper.CreateManagementServiceClient(); //Create Identity Provider var issuer = CreateIdpManually(DateTime.UtcNow, DateTime.UtcNow.AddYears(1), svc, "SelfSTS2", "SelfSTS2", "https://localhost:9000/STS/Issue/", "IdentityTKStsCertForSigning"); //Add the Rules string ruleGroupname = "Default Rule Group for WebSiteAdvancedACS"; AddRulesToRuleGroup(ruleGroupname, issuer.Name); Console.WriteLine("Done!"); }
    FakePre-e2f300f1c0614dff91180b463cccc799-3102975eb08e4111ba0a99509085b20aFakePre-cfd34da8776747a8a8081defc106f2e1-dcb7974e27f147d8b54e5d054932f5e5
    
    Note:
    the ManagementService class is pretty straightforward, mainly plumbing for performing the OData calls.

  21. Finally, change the Main method with the following code.

    (Code Snippet – ACS Labs Federation Lab - Ex01 – Task 5 – Update Main Method - C#)

    C#

      static void Main(string[] args)
    FakePre-c70227d2cf384d399d4511c6bcede314-b19704a261ca4ce19f7e688a30a0f7e9CreateIdentityProviderWithRules(); Console.ReadLine();FakePre-a4e47cc066574a639aa168724ed06137-7d73c05e6b9a49c6afd7b265313b2badFakePre-b3c89ebd6be04153aa5eed324eb772fc-e4a68560797542ec803e917a1b18f43a

  22. Right-click the IdentityProviderSetup project and select Set as StartUp Project.
  23. Press F5 to run the console application. You can see the console and verify that the Identity Provider and the rules were created.

    Figure 36

    The output on the console of the identity provider and rules creation code

  24. You can also verify that the Identity Provider and the rules were created navigating back to the portal. To do this, in the Edit Management Service Account page, click the Return to Management Service link.
  25. Click Return to Access Control Service to go back to the Access Control Service page.
  26. In the Trust Relationships section, click the Identity Providers link. Note that the SelfSTS2 Identity Provider was created.

    Figure 37

    SelfSTS2 Identity Provider verification

  27. Close the browser.
  28. To verify that the new SelftSTS2 Identity Provider is working as expected, execute the SelfSTS.exe file located in Assets\SelfSTS2 folder of this lab.

    Figure 38

    The second SelfSTS instance represents the second Identity Provider

  29. Click the Start button.

    Figure 44

    The second SelfSTS instance now listening for requests

    Note:
    we now have two instances of the SelfSTS utility running, listening on different local ports. In a realistic system the IPs would likely live on completely different systems, representing distinct business entities.

  30. Back to Visual Studio, right-click the https://localhost/WebSiteAdvancedACS/ project and select Set as StartUp Project.
  31. Press F5 to start the Web Site.
  32. Verify that the new Identity Provider SelfSTS2 appears in the Sign In form (you might need to click on the Show more options link).

    Figure 45

    The ACS HDR default page

    Note:
    When we had only one business IP configured in ACS, the authentication phase took place transparently if you exclude some changes in the address bar. Now we have two possible IPs to which we can redirect the user for authenticating, and at this point we have no clue which ACS could use to decide whether to redirect with one or the other. The problem of taking this decision is known as the Home Realm Discovery problem, or HRD, and it arises almost every time there are multiple choices of identity providers. ACS offers various tools to address HDR. The one you can see in Figure 47 is the most direct, in which ACS automatically generates a page with as many buttons as there are configured IPs. Another approach consists of prompting the user for their email address, and using the domain part of it for establishing which IP is the user from (see Figure 24). The advantage of the second approach is that it does not reveal upfront the identity of the IP on the page.

    Both approaches can be mixed and matched, and ACS can even provide the HDR information programmatically so that you can build your own chrome for the HDR, for example if you want to maintain a consistent look & feel with the rest of your application.

  33. Close the browser.
  34. You will now use the Security Token Visualizer Control to see the different claims provided by ACS. To do this, back to Visual Studio, open the Default.aspx file in the WebSiteAdvancedACS project.
  35. From the Visual Studio Toolbox drag and drop a Security Token Visualizer Control at the bottom of the main content control into the Default.aspx page:

    Figure 46

    The Security Token Visualizer Control in Toolbox

    Note:
    Error: Note format was corrupted. Title should be bold.

    ASP.NET

    ...
    <cc1:SecurityTokenVisualizerControl ID="SecurityTokenVisualizerControl1" runat="server" />FakePre-ceebd9d4641a45cbb033435bf6999e59-5c1e97ed1aad4d999e473608d33b8d16

    Note:
     In case no code appears when you drop the control on the page, please close Visual Studio, run the Configuration Wizard again and restart Visual Studio.

  36. Open the Web.config file in the https://localhost/WebSiteAdvancedACS/ project and enable the saveBootstrapTokens attribute inside microsoft.identityModel section:

    XML

    <microsoft.identityModel> <service saveBootstrapTokens="true"> <audienceUris>

  37. Press F5 to start debugging the web application.
  38. In the Sign in page, choose SelfSTS1 Identity Provider in order to authenticate into the Website (you might need to click on the Show more options link).
  39. See the specific claims of the SelfSTS1 Identity Provider.

    Figure 47

    The Security Token Visualizer Control showing the content of the token coming from the first business IP

  40. Close the browser and press F5 to run the solution again.
  41. Choose SelfSTS2 Identity Provider in order to authenticate into the Website (you might need to click on the Show more options link).
  42. See the specific claims of the SelfSTS2 IP.

    Figure 48

    The Security Token Visualizer Control showing the content of the token coming from the second business IP

  43. Close the browser.