The following diagram illustrates the different steps in the claims issuance pipeline that are taken by the STS to process a sign-in request, generate a security token and assign it back to the response message. This is very typical of a passive federation scenario, but can also be used in an active federation where the client directly communicates with the STS to get a security token:
In this recipe, we will create our own implementation of the STS by using various runtime features of WIF.
The following steps will show you the process of defining a contract for the STS along the lines of the claims issuance pipeline:
IdentityManagement
. Add a Visual Studio 2010 C# Class Library Project and name it Common
. System.IdentityModel
and Microsoft.IdentityModel
assemblies. Common
project, create an abstract class—SecureTokenProviderBase
(modify the containing namespace as IdentityService.Common
)—and define the abstract methods— GetSigningCredentials, GetOutputClaimsIdentity, GetEncryptingCredentials, GetTokenLifeTime, SerializeToken, GetAppliesToAddress, GetIssuerName, GetTokenHandler
, and IsEncrypted
, as shown in the following code snippet:public abstract class SecureTokenProviderBase
{
protected abstract SigningCredentials GetSigningCredentials();
protected abstract IClaimsIdentity GetOutputClaimsIdentity();
protected abstract EncryptingCredentials GetEncryptingCredentials();
protected abstract Lifetime GetTokenLifeTime();
protected abstract string SerializeToken(SecurityToken token);
protected abstract string GetAppliesToAddress();
protected abstract string GetIssuerName();
protected abstract SecurityTokenHandler GetTokenHandler();
protected abstract bool IsEncrypted();
}
Notice the signature of the method SerializeToken
. It accepts a generic SecurityToken (System.IdentityModel.Tokens)
instance. This is to allow the implementation to decide the type of token to be serialized into an XML string.
SecurityTokenDescriptor (Microsoft.IdentityModel.Tokens)
for the token, as shown in the following code snippet:public virtual SecurityTokenDescriptor GetSecurityTokenDescriptor() { return new SecurityTokenDescriptor { AppliesToAddress = GetAppliesToAddress(), Lifetime = GetTokenLifeTime(), TokenIssuerName = GetIssuerName(), SigningCredentials = GetSigningCredentials(), EncryptingCredentials = (IsEncrypted()) ? GetEncryptingCredentials() : null, Subject = GetOutputClaimsIdentity() }; }
Note that the method is marked virtual
, indicating that the implementation provided here can be overridden.
public virtual string Issue() { var handler = GetTokenHandler(); var descriptor = GetSecurityTokenDescriptor(); SecurityToken token = handler.CreateToken(descriptor); if (IsEncrypted()) { EncryptedSecurityToken encryptedToken = new EncryptedSecurityToken(token, GetEncryptingCredentials()); return SerializeToken<EncryptedSecurityToken>(encryptedToken); } return SerializeToken<SecurityToken>(token); }
This method can also be overridden in the implemented class.
The SecureTokenProviderBase
abstract class is an attempt to provide a contract for creating a Security Token Service that can issue encrypted tokens (IP-STS). The contract simulates the claims issuance pipeline and allows the implementer to define the signing and encryption mechanism, specify the claims, define the lifetime of the token, specify the endpoint that the token will be applied to, and define a handler for creating the token. The GetSecurityTokenDescriptor
method uses the abstract methods to define the attributes for the token. Finally, the virtual method Issue
uses the handler and the token descriptor to create, encrypt, and serialize a token. Notice that the token is optionally encrypted by checking if the IsEncrypted
method returns a true
value. The STS web application will eventually call this method to get the serialized XML token string and pass it to the RP-STS.
In the next recipe, we will find out how the SecureTokenProviderBase
abstract class is implemented to create an IP-STS that can issue SAML v1.1 tokens.
The SecureTokenProviderBase
class is a part of the solution created to demonstrate the functioning of the claims issuance pipeline and showcase the direct use of the WIF runtime methods that participate in the pipeline process to issue a token. In most cases, the SecurityTokenService
implementation should be good enough, however there maybe cases where a better control is required over the token generation process (such as support for SAML 2.0 Web Browser SSO Profiles). Exercise caution over using the SecureTokenProviderBase
class as-is in a production scenario.