• How to make an Active/Passive STS using “Zermatt” Framework

    Published by on August 20th, 2008 6:41 pm under Geneva, How To, Identity, Zermatt

    No Comments

    Definition

    “A Security Token Service (STS) is the plumbing that builds, signs, and issues security tokens using the interoperable protocols…”

    “The “Zermatt” Framework makes it easy to build your own STS. It’s up to you to figure out how to implement the logic, or rules that drive it (often referred to as security policy).”

    Active vs Passive

      Active STS Passive STS
    Implementation WS-Trust protocol WS-Federation passive protocol
    Built as WCF service ASP.NET web application
    Hosting Self-hosted / IIS IIS

    Steps to create our STS

    1. Implement a custom STS class
    2. Implement a custom STS configuration class
    3. Integrate the STS implementation with the hosting environment. (Here’s the differences between an active and passive STS implementation)

    #1 – Implement a custom STS class

    SecurityTokenService class handles the task of serializing and de-serializing the protocols. We can implement a custom STS by inheriting from this class and providing the following functionality:

    • Decide what claims to issue.
    • Decide what STS signing credentials the STS should use to sign the issued token.
    • Decide what relying party encrypting credentials the STS should use to encrypt the token before sending it (typically, the RP’s certificate information is shared out of band).
    • Decide what URL the response message goes to.

    We need to override two methods from SecurityTokenService class:

    GetScope

    /// <summary>
    /// This methods returns the configuration for the token issuance request. The configuration
    /// is represented by the Scope class.
    /// </summary>
    /// <param name="principal">The caller's principal</param>
    /// <param name="request">The incoming request</param>
    /// <returns></returns>
    protected override Scope GetScope(IClaimsPrincipal principal, RequestSecurityToken request)
    {
                // Validate the request's AppliesTo
                ValidateAppliesTo(request.AppliesTo);
    
                // Create the scope using the request and the STS signing credentials.
                // The request.appliesTo is automatically copied to the scope instance.
                Scope scope = new Scope(request, _signingCreds);
    
                // Setting the encrypting credentials
                scope.EncryptingCredentials = _encryptingCreds;
    
                // Set the ReplyTo address for the WS-Federation passive protocol
                // (THIS IS NOT USED IN THE WS-TRUST ACTIVE CASE)
                scope.ReplyToAddress = scope.AppliesToAddress + "/Default.aspx";
    
                return scope;
    }

    GetOutputSubjects

    /// <summary>
    /// This methods returns the claims to be included in the issued token.
    /// </summary>
    /// <param name="scope">The scope that was previously returned by GetScope method</param>
    /// <param name="principal">The caller's principal</param>
    /// <param name="request">The incoming request</param>
    /// <returns>The claims to be included in the issued token.</returns>
    public override ClaimsIdentityCollection GetOutputSubjects(Scope scope, IClaimsPrincipal principal, RequestSecurityToken request)
    {
                IClaimsIdentity callerIdentity = (IClaimsIdentity)principal.Identity;
                ClaimsIdentity outputIdentity = new ClaimsIdentity();
                ClaimsIdentityCollection returnValue = new ClaimsIdentityCollection();
    
                // Name claim
                outputIdentity.Claims.Add(new Claim(System.IdentityModel.Claims.ClaimTypes.Name, callerIdentity.Name));
    
                // Age Claim (custom claim)
                outputIdentity.Claims.Add(new Claim("http://ZermattSamples/2008/05/AgeClaim", "25", ClaimValueTypes.Integer));
    
                returnValue.Add(outputIdentity);
                return returnValue;
    }

    #2 – Implement a custom STS configuration class

    We can implement a custom STS configuration class by inheriting from SecurityTokenServiceConfiguration class and configuring the following properties:

    • The STS IssuerName. Configure this by passing the value to the base class constructor.
    • The STS implementation class type. Configure this to point to your custom STS implementation class.
    public class MySecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
    {
            public MySecurityTokenServiceConfiguration()
                : base("HelloWorldSTS")
            {
                SecurityTokenService = typeof(MySecurityTokenService);
            }
    }

    #3 – Integrate the STS implementation with the hosting environment

    The integration step varies between active and passive STSes.

    Active STS

    Hosted in a console application
    SecurityTokenServiceConfiguration config = new MySecurityTokenServiceConfiguration();
    
    // Add the STS endoint information
    config.TrustEndpoints.Add(new ServiceHostEndpointConfiguration("http://localhost:6000/HelloWorldSTS", new WSHttpBinding(), typeof(IWSTrustFeb2005SyncContract)));
    
    // Create the WS-Trust service host with our STS configuration
    using (WSTrustServiceHost host = new WSTrustServiceHost(
                config,
                new Uri("http://localhost:6000/HelloWorldSTS")))
    {
                    host.Open();
                    Console.WriteLine("Active STS started, press ENTER to stop ...");
                    Console.ReadLine();
                    host.Close();
    }

    Hosted in a IIS Web-Based Service

    We need to host it in IIS and set up a .svc file in the web site. In this case, the .svc file needs to contain a “Factory” parameter that points to WSTrustServiceHostFactory class or a class inherited from it (if programmatic configuration of the WCF service host is needed), and a “Service” parameter that points to a custom STS configuration class.

    > .svc file:

    <%@ServiceHost language=C#
                    Factory="MyTypes.ActiveSTSFactory"
                    Service="MyTypes.MySecurityTokenServiceConfiguration"%>

    > Custom STS factory:

    // Creating a WSTrustServiceHostFactory instance that is capable of handling WSTrust protocol
    public class ActiveSTSFactory : WSTrustServiceHostFactory
    {
            public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
            {
                // Set the required parameters and return the serviceHost instance
                ServiceHostBase serviceHost = base.CreateServiceHost(constructorString, baseAddresses);
    
                //
                // Perform any necessary imperative configuration of the serviceHost instance here
                //
    
                // return the configured ServiceHost instance to WCF activation
                return serviceHost;
            }
    }

    Passive STS

    Add the custom classes to the web application’s code behind file

    To expose the STS functionality that you have implemented by using the WS-Federation passive protocol, we can use the “Zermatt” Framework FederatedPassiveTokenService control. (Note: make sure that you install the “Zermatt” Framework controls into the Visual Studio toolbox).

    1. Create an ASP.NET web page to handle the WS-Federation passive protocol sign-in requests and add the FederatedPassiveTokenService control.
    2. Set the Service attribute of the control to the type name of your STS configuration class.
    3. When deployed, make sure that the intended authentication is enabled for the passive STS Web application. The FederatedPassiveTokenService control requires that the caller be authenticated before the page is rendered. If the caller of the page is not authenticated, the control will not do anything.
    <idfx:FederatedPassiveTokenService
                ID="TokenService1"
                runat="server"
                Service="PassiveSTS.MySecurityTokenServiceConfiguration">
    </idfx:FederatedPassiveTokenService>

    Tags: , , , ,

  • Leave a comment

    Your email address will not be published.