You can add a custom security token handler simply by creating a
class that derives from SecurityTokenHandler or one of its descendents,
and adding your derived class to the web.config
or
app.config
file for your application. Note that if you
want to write a custom security token handler to handle a
well-known token type, such as SAML 2 or X.509, you must create a
class that derives from the appropriate WIF class. For example, to
handle SAML 2 tokens, you must derive from Saml2SecurityTokenHandler. This topic
shows how to add a custom security token handler that provides
custom username/password validation.
First, create a class that derives from UserNameSecurityTokenHandler and overrides CanValidateToken and ValidateToken.
Copy Code | |
---|---|
using Microsoft.IdentityModel.SecurityTokenService; using Microsoft.IdentityModel.Tokens; namespace SimpleCustomSecurityTokenHandler { public class CustomUserNamePasswordValidatorSecurityTokenHandler : UserNameSecurityTokenHandler { /* Important: You must override CanValidateToken and return true, or your token handler will not be used. */ public override bool CanValidateToken { get { return true; } } public override ClaimsIdentityCollection ValidateToken(SecurityToken token) { if (token == null) { throw new ArgumentNullException(); } UserNameSecurityToken UNtoken = token as UserNameSecurityToken; if (UNtoken == null) { throw new SecurityTokenException("Invalid token"); } /* Validate UNtoken.UserName and UNtoken.Password here. */ Claim claim = new Claim(System.IdentityModel.Claims.ClaimTypes.Name, UNtoken.UserName); IClaimsIdentity identity = new ClaimsIdentity(nameClaim,"Password"); identity.Claims.Add( new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/ClaimTypes.AuthenticationInstant", XmlConvert.ToString(DateTime.UtcNow, "yyyy-MM-ddTHH:mm:ss.fffZ"), "http://www.w3.org/2001/XMLSchema#dateTime") ); identity.Claims.Add( new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/ClaimTypes.AuthenticationMethod", "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password") ); return new ClaimsIdentityCollection(new IClaimsIdentity[] { identity }); } } } |
Next, add the custom token handler to the service
configuration by adding the following markup to the
configuration
section of the service’s
app.config
file.
Copy Code | |
---|---|
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <!-- Registers the microsoft.IdentityModel configuration section --> <section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </configSections> <microsoft.identityModel> <service> <securityTokenHandlers> <remove type="Microsoft.IdentityModel.Tokens.UserNameSecurityTokenHandler, Microsoft.IdentityModel, Version=0.6.1.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/> <add type="SimpleCustomSecurityTokenHandler.CustomUserNamePasswordValidatorSecurityTokenHandler, SimpleCustomSecurityTokenHandler"/> </securityTokenHandlers> </service> </microsoft.identityModel> </configuration> |
Note that not only do we add our custom security token
handler,
CustomUserNamePasswordValidatorSecurityTokenHandler
,
we also remove the default username/password security token
handler, UserNameSecurityTokenHandler. This is
because WIF’s token handler collection will, by default, contain
only one token handler for each token type. There is a one-to-one
relationship between token handlers and token types, so you should
not write a custom token handler to handle more than one token
type. A token type might be represented by one or more token
identifier strings, so you can write a custom token handler to
handle one token type and more than one token identifier.
If your custom security token handler overrides ReadToken, it must also override CanReadToken. Likewise, if it overrides WriteToken, it must also override CanWriteToken.