How can WIF help in simplifying WCF security ?
Traditionally we have UserNamePasswordValidator class to do the job from WCF layer (http://msdn.microsoft.com/en-us/library/aa702565.aspx).
But not good for developer, they would like to implement the business logic inside methods and will never like to take headache for implementing security.
WIF to rescue
Using WIF we can take out the security aspect completely out of WCF and implement at level of STS.
This will help developers in concentrating on core BL development rather than on security implementation.
Steps to validate the User name pass word via WIF provided STS service.
Now we have brand new STS project added to our main solution
1. Checking configuration file for STS
<ws2007HttpBinding>
<binding name="ws2007HttpBindingConfiguration">
<security mode="Message">
<message establishSecurityContext="false" />
</security>
</binding>
</ws2007HttpBinding>
2. We need the client to send user name password, right !
<message establishSecurityContext="false" clientCredentialType="UserName"/>
3. Also add the service certificate inside service behavior.
<serviceCredentials>
<serviceCertificate findValue="saurabh.xyz.microsoft.com" storeLocation="LocalMachine" storeName="My" x509FindType="FindByIssuerName"/>
</serviceCredentials>
4. Now, the flow will be like this.
5. Now the STS is configured to ask for a User Name token, next step is to validate the same. We can use the WIF provided “UserNameSecurityTokenHandler“ to validate the incoming token.
public class CustomUserNameSecurityTokenHandler : UserNameSecurityTokenHandler Override the canValidateToken and ValidateToken methods
public override bool CanValidateToken
{
get { return true; }
}
public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
UserNameSecurityToken usernameToken = token as UserNameSecurityToken;
if (usernameToken == null)
throw new ArgumentException("usernameToken", "The security token is not a valid username security token.");
string username = usernameToken.UserName;
string password = usernameToken.Password;
if (("myUser"== username && "myPass" ==password))
IClaimsIdentity identity = new ClaimsIdentity();
identity.Claims.Add(new Claim(WSIdentityConstants.ClaimTypes.Name,username));
return new ClaimsIdentityCollection(new IClaimsIdentity[] { identity });
throw new InvalidOperationException("The username/password is incorrect");
6. Once we are done with this, let us refer the same from the configuration file.
Add below tag inside configuration tag
<microsoft.identityModel>
<service>
<securityTokenHandlers>
<remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler,Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add type="CustomUserNameSecurityTokenHandler,App_Code"/>
</securityTokenHandlers>
</service>
</microsoft.identityModel>
7. Now if we try to re-build it will give an error.
8. Please add below code to correct this.
<configSections>
<section name="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection,Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" />
</configSections>
9. That’s it. We have successfully added the security layer using WIF inside the WCF service.
10 . Next step is to create the client project and add service reference to WCF service.
11. Add following code to main method
static void Main(string[] args)
ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client();
proxy.ClientCredentials.UserName.UserName = "myUser";
proxy.ClientCredentials.UserName.Password = "myPass";
Console.WriteLine(proxy.GetData(123));
12. We can validate the validation by adding break point inside the “CustomUserNameSecurityTokenHandler.cs” class.
Hope this helps !