A reader has asked me to update the Client SAML sample to WIF RTM (for background and motivation please read here first).
The main work was in the SAML security token handler Validate method, this looks now like this:
public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
{
if (token == null)
{
throw new ArgumentNullException(“token”);
}
var samlToken = token as SamlSecurityToken;
if (samlToken == null)
{
throw new ArgumentException(“token”);
}
if (samlToken.Assertion == null)
{
throw new ArgumentException(“token”);
}
var assertion = samlToken.Assertion as Saml11Assertion;
this.ValidateConditions(samlToken.Assertion.Conditions, false);
// extract claims from token
var identity = new ClaimsIdentity(“ClientSaml”);
ProcessStatement(assertion.Statements, identity, “Client”);
// call authentication and filtering logic
IClaimsIdentity newIdentity;
try
{
if (ValidateUser(identity, out newIdentity))
{
return new ClaimsIdentityCollection(new IClaimsIdentity[] { newIdentity });
}
else
{
throw new SecurityTokenValidationException(“Authentication failed”);
}
}
catch (Exception ex)
{
throw new SecurityTokenValidationException(“Security token validation failed”, ex);
}
}
You would then derive from the base handler and implement the ValidateUser method. This method does some sort of authentication based on the incoming claims and returns an IClaimsIdentity containing the claims that should get passed through to the service code, e.g.:
// sample implementation – do not use for production ;)
protected override bool ValidateUser(ClaimsIdentity id, out IClaimsIdentity newIdentity)
{
newIdentity = null;
var usernameClaim = id.Claims.First(c => c.ClaimType == WSIdentityConstants.ClaimTypes.Name);
var passwordClaim = id.Claims.First(c => c.ClaimType == _passwordClaimType);
var customerIdClaim = id.Claims.First(c => c.ClaimType == _customerIdClaimType);
if (usernameClaim.Value == passwordClaim.Value)
{
newIdentity = new ClaimsIdentity(new Claim[]
{
usernameClaim,
customerIdClaim
}, “ClientSaml”);
return true;
}
return false;
}
You can find the complete source code here.
Thanks for the write-up. The issue at hand is that we have a WSDL that was provided for integration, and 2 operations require SAML 2.0 assertions, whereas one does not. For the operations that require SAML 2.0 assertion, developing a client using .Net 4.0, what is the best way to integrate SAML 2.0 components? WIF has a CTP that does not have backward compatibility with the prior version installed with VS2012 (.net 3.5 version I believe), and we are therefore stuck having to override the SOAP header using the IClientMessageInspector methods.