Bewerken

Share via


SecurityTokenService Class

Definition

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

public ref class SecurityTokenService abstract
public abstract class SecurityTokenService
type SecurityTokenService = class
Public MustInherit Class SecurityTokenService
Inheritance
SecurityTokenService

Examples

The code examples that are used in the SecurityTokenService topics are taken from the Custom Token sample. This sample provides custom classes that enable processing of Simple Web Tokens (SWT) and it includes an implementation of a passive STS that is capable of serving an SWT token. For an example of how to implement an active STS, you can see the Federation Metadata sample. For information about these samples and other samples available for WIF and about where to download them, see WIF Code Sample Index. The following code shows the implementation of a passive STS using the SecurityTokenService class.

using System;
using System.IdentityModel;
using System.IdentityModel.Configuration;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;

namespace PassiveSTS
{
    /// <summary>
    /// Overrides the SecurityTokenService class to provide
    /// the relying party related information, such as encryption credentials to encrypt the issued
    /// token, signing credentials to sign the issued token, claims that the STS wants to issue for a 
    /// certain token request, as well as the claim types that this STS is capable
    /// of issuing.
    /// </summary>
    public class CustomSecurityTokenService : SecurityTokenService
    {
        // Certificate Constants
        private const string SIGNING_CERTIFICATE_NAME = "CN=localhost";
        private const string ENCRYPTING_CERTIFICATE_NAME = "CN=localhost";

        private SigningCredentials _signingCreds;
        private EncryptingCredentials _encryptingCreds;
        // Used for validating applies to address, set to URI used in RP app of application, could also have been done via config
        private string _addressExpected = "http://localhost:19851/";
        public CustomSecurityTokenService(SecurityTokenServiceConfiguration configuration)
            : base(configuration)
        {
            // Setup the certificate our STS is going to use to sign the issued tokens
            _signingCreds = new X509SigningCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, SIGNING_CERTIFICATE_NAME));

            // Note: In this sample app only a si   ngle RP identity is shown, which is localhost, and the certificate of that RP is 
            // populated as _encryptingCreds
            // If you have multiple RPs for the STS you would select the certificate that is specific to 
            // the RP that requests the token and then use that for _encryptingCreds
            _encryptingCreds = new X509EncryptingCredentials(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, ENCRYPTING_CERTIFICATE_NAME));
        }

        /// <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 the _encryptingCreds field.
        /// </summary>
        /// <param name="principal">The caller's principal</param>
        /// <param name="request">The incoming RST</param>
        /// <returns></returns>
        protected override Scope GetScope(ClaimsPrincipal principal, RequestSecurityToken request)
        {
            // Validate the AppliesTo address
            ValidateAppliesTo( request.AppliesTo );

            // Create the scope using the request AppliesTo address and the RP identity
            Scope scope = new Scope( request.AppliesTo.Uri.AbsoluteUri, _signingCreds );

            if (Uri.IsWellFormedUriString(request.ReplyTo, UriKind.Absolute))
            {
                if (request.AppliesTo.Uri.Host != new Uri(request.ReplyTo).Host)
                    scope.ReplyToAddress = request.AppliesTo.Uri.AbsoluteUri;
                else
                    scope.ReplyToAddress = request.ReplyTo;
            }
            else
            {
                Uri resultUri = null;
                if (Uri.TryCreate(request.AppliesTo.Uri, request.ReplyTo, out resultUri))
                    scope.ReplyToAddress = resultUri.AbsoluteUri;
                else
                    scope.ReplyToAddress = request.AppliesTo.Uri.ToString() ;
            }

            // Note: In this sample app only a single RP identity is shown, which is localhost, and the certificate of that RP is 
            // populated as _encryptingCreds
            // If you have multiple RPs for the STS you would select the certificate that is specific to 
            // the RP that requests the token and then use that for _encryptingCreds
            scope.EncryptingCredentials = _encryptingCreds;

            return scope;
        }
        /// <summary>
        /// This method returns the content of the issued token. The content is represented as a set of
        /// IClaimIdentity intances, each instance corresponds to a single issued token. Currently, the Windows Identity Foundation only
        /// supports a single token issuance, so the returned collection must always contain only a single instance.
        /// </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, we don't use this in our implementation</param>
        /// <returns></returns>
        protected override ClaimsIdentity GetOutputClaimsIdentity( ClaimsPrincipal principal, RequestSecurityToken request, Scope scope )
        {
            //
            // Return a default claim set which contains a custom decision claim
            // Here you can actually examine the user by looking at the IClaimsPrincipal and 
            // return the right decision based on that. 
            //
            ClaimsIdentity outgoingIdentity = new ClaimsIdentity();
            outgoingIdentity.AddClaims(principal.Claims);

            return outgoingIdentity;
        }
        /// <summary>
        /// Validates the appliesTo and throws an exception if the appliesTo is null or appliesTo contains some unexpected address.
        /// </summary>
        /// <param name="appliesTo">The AppliesTo parameter in the request that came in (RST)</param>
        /// <returns></returns>
        void ValidateAppliesTo(EndpointReference appliesTo)
        {
            if (appliesTo == null)
            {
                throw new InvalidRequestException("The appliesTo is null.");
            }

            if (!appliesTo.Uri.Equals(new Uri(_addressExpected)))
            {
                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));
            }
        }

    }
}

The following code shows how to invoke a custom passive STS to process a WS-Federation request by calling the FederatedPassiveSecurityTokenServiceOperations.ProcessRequest(HttpRequest, ClaimsPrincipal, SecurityTokenService, HttpResponse) method from the code behind in the default.aspx.cs file.

using System;
using System.IdentityModel.Services;
using System.Security.Claims;

namespace PassiveSTS
{
    public partial class _Default : System.Web.UI.Page
    {
        /// <summary>
        /// We perform the WS-Federation Passive Protocol processing in this method. 
        /// </summary>
        protected void Page_PreRender( object sender, EventArgs e ) 
        {
            FederatedPassiveSecurityTokenServiceOperations.ProcessRequest( Request, User as ClaimsPrincipal, CustomSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService(), Response );
        }
    }
}

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 using Windows Identity Foundation (WIF) will be developing applications that outsource identity management to an STS, rather than developing an STS itself. WIF provides a Visual Studio extension, the Identity and Access Tool for Visual Studio 2012, to help developers test solutions in the development environment. This tool includes an STS, LocalSTS, that you can configure to serve specific claims to the application that you are developing. For more information about the Identity and Access tool, see Identity and Access Tool for Visual Studio 2012. In some scenarios, LocalSTS may not provide the functionality necessary to adequately test your application; for example, in a scenario that involves developing a custom token handler for use by an application. In these cases, you can derive from SecurityTokenService to create one or more simple STSs that can be deployed in your development environment and that can be used to test such features in your application. The rest of this section focuses on the methods exposed by the SecurityTokenService 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 ClaimsIdentity 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.

An STS is configured through the SecurityTokenServiceConfiguration class.

Notes to Implementers

You must override both the GetScope(ClaimsPrincipal, RequestSecurityToken) and the GetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope) methods.

Constructors

SecurityTokenService(SecurityTokenServiceConfiguration)

Called from derived classes to initialize the SecurityTokenService class using the specified configuration settings.

Properties

Principal

Gets or sets the principal associated with the current instance.

Request

Gets or sets the security token request (RST) associated with the current instance.

Scope

Gets or sets the scope associated with the current instance.

SecurityTokenDescriptor

Gets or sets the SecurityTokenDescriptor associated with the current instance.

SecurityTokenServiceConfiguration

Gets the owner configuration instance.

Methods

BeginCancel(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

When overridden in a derived class, begins an asynchronous WS-Trust Cancel request.

BeginGetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope, AsyncCallback, Object)

When overridden in a derived class, begins an asynchronous call to the GetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope) method.

BeginGetScope(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

When overridden in a derived class, begins an asynchronous call for the GetScope(ClaimsPrincipal, RequestSecurityToken) method.

BeginIssue(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

When overridden in a derived class, begins an asynchronous WS-Trust Issue request.

BeginRenew(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

When overridden in a derived class, begins an asynchronous WS-Trust Renew request.

BeginValidate(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object)

When overridden in a derived class, begins an asynchronous WS-Trust Validate request.

Cancel(ClaimsPrincipal, RequestSecurityToken)

When overridden in a derived class, processes a WS-Trust Cancel request.

CreateSecurityTokenDescriptor(RequestSecurityToken, Scope)

Creates an instance of a SecurityTokenDescriptor.

EndCancel(IAsyncResult)

When overridden in a derived class, completes the asynchronous WS-Trust Cancel request.

EndGetOutputClaimsIdentity(IAsyncResult)

When overridden in a derived class, completes the asynchronous call to the BeginGetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope, AsyncCallback, Object) method.

EndGetScope(IAsyncResult)

When overridden in a derived class, completes the asynchronous call to the BeginGetScope(ClaimsPrincipal, RequestSecurityToken, AsyncCallback, Object) method.

EndIssue(IAsyncResult)

When overridden in a derived class, completes the asynchronous WS-Trust Issue request.

EndRenew(IAsyncResult)

When overridden in a derived class, completes the asynchronous WS-Trust Renew request.

EndValidate(IAsyncResult)

When overridden in a derived class, completes the asynchronous WS-Trust Validate request.

Equals(Object)

Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetHashCode()

Serves as the default hash function.

(Inherited from Object)
GetIssuerName()

Gets the name of the security token service (STS).

GetOutputClaimsIdentity(ClaimsPrincipal, RequestSecurityToken, Scope)

When overridden in a derived class, this method returns a collection of output subjects to be included in the issued token.

GetProofToken(RequestSecurityToken, Scope)

Gets the proof token to be included in the response (RSTR).

GetRequestorProofEncryptingCredentials(RequestSecurityToken)

Gets the requestor's proof encrypting credentials.

GetResponse(RequestSecurityToken, SecurityTokenDescriptor)

Creates the response (RSTR) that contains the issued token by using the specified request (RST) and security token descriptor.

GetScope(ClaimsPrincipal, RequestSecurityToken)

Gets a Scope object that contains information about the relying party (RP) associated with the specified request (RST). You must override this method in your implementation of the SecurityTokenService class.

GetSecurityTokenHandler(String)

Gets the appropriate security token handler for issuing a security token of the specified type.

GetTokenLifetime(Lifetime)

Gets the lifetime for the issued token.

GetType()

Gets the Type of the current instance.

(Inherited from Object)
Issue(ClaimsPrincipal, RequestSecurityToken)

Issues a security token.

MemberwiseClone()

Creates a shallow copy of the current Object.

(Inherited from Object)
Renew(ClaimsPrincipal, RequestSecurityToken)

When overridden in a derived class, processes a WS-Trust Renew request.

ToString()

Returns a string that represents the current object.

(Inherited from Object)
Validate(ClaimsPrincipal, RequestSecurityToken)

When overridden in a derived class, processes a WS-Trust Validate request.

ValidateRequest(RequestSecurityToken)

Validates the security token request (RST) encapsulated by this instance.

Applies to

See also