I use this configuration:
<message clientCredentialType=“UserName“ />
In the client, you now have to explicitly pass in a username and password:
var factory = new ChannelFactory<IClaimsService>(“*”);
factory.Credentials.UserName.UserName = “username”;
factory.Credentials.UserName.Password = “password”;
var proxy = factory.CreateChannel();
var id = proxy.GetIdentity();
By default WCF will check the credentials against the Windows account database, and if authentication is successful, you get a full fledged WindowsPrincipal/WindowsIdentity in your service (just as with Windows integrated authentication).
Custom AuthenticationWhen you want to authenticate against a custom credential store, you need to configure a custom password validator that in the <serviceCredentials /> behavior:
customUserNamePasswordValidatorType=“Type, Assembly“ />
A sample implementation looks like this:
public class PasswordValidator : UserNamePasswordValidator
public override void Validate(string userName, string password)
if (userName != password)
throw new SecurityTokenValidationException();
Now when you run that, you’ll notice that you get an anonymous WindowsPrincipal onThread.CurrentPrincipal. And the only way to get to the client’s username is via theServiceSecurityContext. So this “old” approach is not really compatible with the claims world.
Enabling “WIF” Mode
In WIF mode you have much better claims integration, but there are also some changes you need to do to your authentication code. But first of all, enable WIF mode:
<serviceCredentials useIdentityConfiguration=“true“ />
The standard token handler again authenticates against Windows accounts. When you want to authenticate against your custom credential store, you need to supply a custom security token handler. This is not as simple as writing a password validator like the one above, but fortunately I have a really simpler wrapper in our Thinktecture.IdentityModellibrary.
You could configure your token handler also in configuration, but you can also do it via code:
host.Credentials.UseIdentityConfiguration = true;
var idConfig = new IdentityConfiguration();
new GenericUserNameSecurityTokenHandler((uname, password) =>
uname == password));
host.Credentials.IdentityConfiguration = idConfig;
…or if you simply want to wrap an existing password validator:
(uname, password) =>
var validator = new PasswordValidator();
The final step is to tell WCF to put the ClaimsPrincipal coming from the token handler onThread.CurrentPrincipal using the following service behavior:
<serviceAuthorization principalPermissionMode=“Always“ />
The end result is a ClaimsPrincipal containing the username, authentication method and authentication instant claims. Also the claims transformation/validation/authorization pipeline will be called if configured.