SecurityTokenService Class

[Starting with the .NET Framework 4.5, Windows Identity Foundation (WIF) has been fully integrated into the .NET Framework. The version of WIF addressed by this topic, WIF 3.5, is deprecated and should only be used when developing against the .NET Framework 3.5 SP1 or the .NET Framework 4. For more information about WIF in the .NET Framework 4.5, also known as WIF 4.5, see the Windows Identity Foundation documentation in the .NET Framework 4.5 Development Guide.]

The abstract class that defines the properties and methods of a security token service (STS).

Namespace: Microsoft.IdentityModel.SecurityTokenService
Assembly: Microsoft.IdentityModel (in Microsoft.IdentityModel.dll)

Usage

'Usage
Dim instance As SecurityTokenService

Syntax

'Declaration
Public MustInherit Class SecurityTokenService
public abstract class SecurityTokenService
public ref class SecurityTokenService abstract
public abstract class SecurityTokenService
public abstract class SecurityTokenService

Example

The following code example implements a simple STS that will provide claims for a service at the following address: https://localhost:6020/ClaimsAwareWebService. The STS provides a name claim and an age claim to the service.

using System;
using System.ServiceModel;

using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Configuration;
using Microsoft.IdentityModel.Protocols.WSTrust;
using Microsoft.IdentityModel.SecurityTokenService;

namespace ClaimsAwareWebService
{
    public class MySecurityTokenService : SecurityTokenService
    {
        const string addressExpected = "https://localhost:6020/ClaimsAwareWebService";
        const string encryptingCertificateName = "CN=localhost";

        /// <summary>
        /// Creates an instance of the MySecurityTokenService class.
        /// </summary>
        /// <param name="configuration">SecurityTokenServiceConfiguration element.</param>
 
        public MySecurityTokenService( SecurityTokenServiceConfiguration configuration )
            : base( configuration )
        {
        }

        /// <summary>
        /// This method returns the configuration for the token issuance request. The configuration
        /// is represented by the Scope class. In our case, we are only capable of issuing a token to a
        /// single RP identity represented by CN=localhost.
        /// </summary>
        /// <param name="principal">The caller's principal</param>
        /// <param name="request">The incoming RST</param>
        /// <returns>The configuration for the token issuance request.</returns>
        protected override Scope GetScope( IClaimsPrincipal principal, RequestSecurityToken request )
        {
            // Validate the AppliesTo on the incoming request
            ValidateAppliesTo( request.AppliesTo );

            // Normally the STS will have a trust relationship with the RP and can look up a trusted encrypting certficate 
            // using the AppliesTo endpoint. This is necessary to ensure that only the RP will be able to read the claims.
            //
            // In this sample the certificate of the AppliesTo Identity is used to encrypt the contents, so there is no
            // validation of any trust relationship with the RP. Since the certificate is not validated, 
            // a malicious client can provide a known certificate allowing it to read the returned claims.
            // For this reason, THIS APPROACH SHOULD NOT BE USED if the claims should be kept private. It may be reasonable,
            // though, if the STS is simply verifying public information such as the client's email address.

            // Get RP certificate
            X509CertificateEndpointIdentity appliesToIdentity = (X509CertificateEndpointIdentity)request.AppliesTo.Identity;

            X509EncryptingCredentials encryptingCredentials = new X509EncryptingCredentials( appliesToIdentity.Certificates[0] );
            // Create the scope using the request AppliesTo address and the STS signing certificate
            Scope scope = new Scope( request.AppliesTo.Uri.AbsoluteUri, SecurityTokenServiceConfiguration.SigningCredentials, encryptingCredentials );
            return scope;
        }

        /// <summary>
        /// Validates the appliesTo and throws an exception if the appliesTo is null or appliesTo contains some unexpected address.  
        /// </summary>
        void ValidateAppliesTo( EndpointAddress appliesTo )
        {
            if ( appliesTo == null )
            {
                throw new InvalidRequestException( "The appliesTo is null." );
            }

            if ( !appliesTo.Uri.Equals( new Uri( addressExpected ) ) )
            {
                Console.WriteLine( "The relying party address is not valid. " );
                throw new InvalidRequestException( String.Format( "The relying party address is not valid. Expected value is {0}, the actual value is {1}.", addressExpected, appliesTo.Uri.AbsoluteUri ) );
            }
        }


        /// <summary>
        /// This method 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 RST</param>
        /// <returns>The claims to be included in the issued token.</returns>
        protected override IClaimsIdentity GetOutputClaimsIdentity(IClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
        {


            if ( null == principal )
            {
                throw new InvalidRequestException("The caller's principal is null.");
            }



            // Get the incoming IClaimsIdentity from IPrincipal 
            IClaimsIdentity callerIdentity = (IClaimsIdentity)principal.Identity;

            
            // Create the output IClaimsIdentity
            IClaimsIdentity outputIdentity = new ClaimsIdentity();

            // Create a name claim from the incoming identity.
            Claim nameClaim = new Claim( ClaimTypes.Name, callerIdentity.Name );

            // Create an 'Age' claim with a value of 25. In a real scenario, this may likely be looked up from a database.
            Claim ageClaim = new Claim( "http://WindowsIdentityFoundationSamples/2008/05/AgeClaim", "25", ClaimValueTypes.Integer );

            // Add the name
            outputIdentity.Claims.Add( nameClaim );
            outputIdentity.Claims.Add( ageClaim );

            return outputIdentity;
        }


    }
}

Remarks

To create an STS you must derive from the SecurityTokenService class. In your custom class you must, at a minimum, override the GetScope and GetOutputClaimsIdentity methods. With these overrides, the STS created using the default implementation of all the other methods defined in the class is capable of issuing security tokens in response to security token requests (RST). That is, the Issue binding defined in the WS-Trust specification is implemented. This binding is implemented in the Issue method. None of the other WS-Trust bindings (Renew, Cancel, and Validate) are implemented in the default case and an appropriate fault is returned to the caller if an RST that corresponds to one of these bindings is encountered. You can, of course, override the appropriate methods (Renew, Cancel, and Validate) to implement these bindings in your STS.

Important

Implementing a production-ready STS entails careful planning and considerable resources to mitigate the potential security risks inherent in exposing such a service. Most developers will use the SecurityTokenService class to extend the implementation provided by the Visual Studio templates or to create simple STSs that can be deployed in the development environment and that can be used to test specific features in a relying party (RP) or active client under development. For this reason, the rest of this section focuses on the methods exposed by the class that enable you to implement a simple STS and extend the token issuance pipeline.

The following list provides a brief overview of the methods of primary importance to the developer for use in a test or development environment.

  • The GetScope method. This method returns a Scope object that contains information about the RP. This object is used in the rest of the token issuance pipeline and includes information about the signing and encrypting credentials to use in the response, as well as the AppliesTo and ReplyTo (if required) addresses. You must override this method.

  • The GetOutputClaimsIdentity method. This method returns an IClaimsIdentity object that contains the claims to return to the RP. You must override this method.

  • The Issue method. This method implements the token request pipeline, which processes an incoming security token request (RST) and returns a response (RSTR) to the caller that contains a token that can be used to authenticate with an RP. Many of the other methods defined in the SecurityTokenService class are called from this method, including the GetScope and GetOutputClaimsIdentity methods. You do not have to override this method, but an understanding of the token request pipeline it implements may be helpful. For more information about the token issuance pipeline, see the Claims Issuance Pipeline topic.

For more information about STSs and how to build STSs using Windows® Identity Foundation (WIF), see the topics under the Claims Provider - Security Token Service topic.

An STS is configured through the SecurityTokenServiceConfiguration class. For more information about configuring an STS, see the Configuration topic.

All of the WIF samples contain custom STS implementations. For examples of simple STS implementations, see the samples in the Quick Start directory. For examples of more complicated STS implementations, including STSs used in delegation and federation scenarios, see the samples in the End-to-end and Extensibility directories.

Notes to Inheritors: You must override both the GetScope and the GetOutputClaimsIdentity methods.

Inheritance Hierarchy

System.Object
  Microsoft.IdentityModel.SecurityTokenService.SecurityTokenService

Thread Safety

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Platforms

Target Platforms

Windows 7, Windows Server 2008 R2, Windows Vista SP2, Windows Server 2008 SP2, Windows Server 2003 SP2 (32-bit or 64-bit)

Change History

See Also

Reference

SecurityTokenService Members
Microsoft.IdentityModel.SecurityTokenService Namespace

Other Resources

Claims Provider - Security Token Service
Claims Issuance Pipeline
Configuration

Copyright © 2008 by Microsoft Corporation. All rights reserved.