When working with Claims Based Authentication a lot of things are similar between the two different models, Active and Passive. However, there are a few cases where things differ… a lot. The biggest of course being how a Request for Security Token (RST) is authenticated. In a passive model the user is given a web page where they can essentially have full reign over how credentials are handled. Once the credentials have been received and authenticated by the web server, the server generates an identity and passes it off to SecurityTokenService.Issue(…) and does it’s thing by gathering claims, packaging them up into a token, and POST’ing the token back to the Relying Party.
Basically we are handling authentication any other way an ASP.NET application would, by using the Membership provider and funnelling all anonymous users to the login page, and then redirecting back to the STS. To hand off to the STS, we can just call:
FederatedPassiveSecurityTokenServiceOperations.ProcessRequest(
HttpContext.Current.Request,
HttpContext.Current.User,
MyTokenServiceConfiguration.Current.CreateSecurityTokenService(),
HttpContext.Current.Response);
However, it’s a little different with the active model.
Web services manage identity via tokens but they differ from passive models because everything is passed via tokens including credentials. The client consumes the credentials and packages them into a SecurityToken object which is serialized and passed to the STS. The STS deserializes the token and passes it off to a SecurityTokenHandler. This security token handler validates the credentials and generates an identity and pushes it up the call stack to the STS.
Much like with ASP.NET, there is a built in Membership Provider for username/password combinations, but you are limited to the basic functionality of the provider. 90% of the time, this is probably just fine. Other times you may need to create your own SecurityTokenHandler. It’s actually not that hard to do.
First you need to know what sort of token is being passed across the wire. The big three are:
- UserNameSecurityToken – Has a username and password pair
- WindowsSecurityToken – Used for Windows authentication using NTLM or Kerberos
- X509SecurityToken – Uses x509 certificate for authentication
Each is pretty self explanatory.
Some others out of the box are:

Reflector is an awesome tool. Just sayin’.
Now that we know what type of token we are expecting we can build the token handler. For the sake of simplicity let’s create one for the UserNameSecurityToken.
To do that we create a new class derived from Microsoft.IdentityModel.Tokens.UserNameSecurityTokenHandler. We could start at SecurityTokenHandler, but it’s an abstract class and requires a lot to get it working. Suffice to say it’s mostly boilerplate code.
We now need to override a method and property: ValidateToken(SecurityToken token) and TokenType.
TokenType is used later on to tell what kind of token the handler can actually validate. More on that in a minute.
Overriding ValidateToken is fairly trivial*. This is where we actually handle the authentication. However, it returns a ClaimsIdentityCollection instead of bool, so if the credentials are invalid we need to throw an exception. I would recommend the SecurityTokenValidationException. Once the authentication is done we get the identity for the credentials and bundle them up into a ClaimsIdentityCollection. We can do that by creating an IClaimsIdentity and passing it into the constructor of a ClaimsIdentityCollection.
public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
{
UserNameSecurityToken userToken = token as UserNameSecurityToken;
if (userToken == null)
throw new ArgumentNullException("token");
string username = userToken.UserName;
string pass = userToken.Password;
if (!Membership.ValidateUser(username, pass))
throw new SecurityTokenValidationException("Username or password is wrong.");
IClaimsIdentity ident = new ClaimsIdentity();
ident.Claims.Add(new Claim(WSIdentityConstants.ClaimTypes.Name, username));
return new ClaimsIdentityCollection(new IClaimsIdentity[] { ident });
}
Next we need set the TokenType:
public override Type TokenType
{
get
{
return typeof(UserNameSecurityToken);
}
}
This property is used as a way to tell it’s calling parent that it can validate/authenticate any tokens of the type it returns. The web service that acts as the STS loads a collection SecurityTokenHandler’s as part of it’s initialization and when it receives a token it iterates through the collection looking for one that can handle it.
To add the handler to the collection you add it via configuration or if you are crazy doing a lot of low level work you can add it to the SecurityTokenServiceConfiguration in the HostFactory for the service:
securityTokenServiceConfiguration.SecurityTokenHandlers.Add(new MyAwesomeUserNameSecurityTokenHandler())
To add it via configuration you first need to remove any other handlers that can validate the same type of token:
<microsoft.identityModel>
<service>
<securityTokenHandlers>
<remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<remove type="Microsoft.IdentityModel.Tokens.MembershipUserNameSecurityTokenHandler,
Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add type="Syfuhs.IdentityModel.Tokens.MyAwesomeUserNameSecurityTokenHandler, Syfuhs.IdentityModel" />
</securityTokenHandlers>
That’s pretty much all there is to it. Here is the class for the sake of completeness:
using System;
using System.IdentityModel.Tokens;
using System.Web.Security;
using Microsoft.IdentityModel.Claims;
using Microsoft.IdentityModel.Protocols.WSIdentity;
using Microsoft.IdentityModel.Tokens;
namespace Syfuhs.IdentityModel.Tokens
{
public class MyAwesomeUserNameSecurityTokenHandler : UserNameSecurityTokenHandler
{
public override bool CanValidateToken { get { return true; } }
public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
{
UserNameSecurityToken userToken = token as UserNameSecurityToken;
if (userToken == null)
throw new ArgumentNullException("token");
string username = userToken.UserName;
string pass = userToken.Password;
if (!Membership.ValidateUser(username, pass))
throw new SecurityTokenValidationException("Username or password is wrong.");
IClaimsIdentity ident = new ClaimsIdentity();
ident.Claims.Add(new Claim(WSIdentityConstants.ClaimTypes.Name, username));
return new ClaimsIdentityCollection(new IClaimsIdentity[] { ident });
}
}
}
* Trivial in the development sense, not trivial in the security sense.