Via this post.
Clean up the files not needed after SP1 installation.
"vsp1cln.exe is added to your Windows Vista System folder after you install Vista SP1."
In our project we build services in the intranet zone, therefore windows authentication is really the most simple and sufficient authentication mode for us.
Lately though, we have encountered continuing troubles with Kerberos Delegation,
Most of the times it was due to domain settings (delegation trust / spns and such), unfortunately, in the other times we discovered it's actually hardware issues - We needed to update the user's network adapter drivers.
We decided No More, let's look into different approach that will replace it.
I headed to work and found a great sample in the SDK called 'Trusted Facade'.
Service Side:
We create a custom binding that uses a tcp transport with windows stream security but the authentication mode is set to UserNameOverTransport.
This essentially means the binding will be over TCP, accepting calls from windows account users but the authentication will be done for the username being passed on the transport, allowing a client to call with a constant windows identity but passing the actual caller's username onto the transport.
<
customBinding>
<binding name="TcpUserNameBinding">
<security authenticationMode="UserNameOverTransport" />
<windowsStreamSecurity />
<tcpTransport maxReceivedMessageSize="2147483646" />
</binding>
</customBinding>
We create the service behavior and setting the service credentials.
Since this is no longer windows integrated, we could use the aspnet membership provider but since the client passes a windows account's username and not an aspnet user I will set it to custom.
The PasswordValidator doesn't do much, simply throws an exception if the username is null or empty, in some cases I check for an expected password that only valid clients will know of, anyway, you can implement any logic that suits you.
<
behavior name="CustomUserNamePasswordValidatorBehavior">
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Zuker.Solutions.ServiceModel.Security.SecuredUserNamePasswordValidator, Zuker.Solutions.ServiceModel" />
</serviceCredentials>
</behavior>
We set the endpoint - bind it to our binding and behavior, then of course - hosting it up.
Client Side
We set the configuration pretty much a like, create the custom binding and bind it to our endpoint.
<customBinding>
<binding name="TcpUserNameBinding">
<security authenticationMode="UserNameOverTransport" />
<windowsStreamSecurity />
<tcpTransport maxReceivedMessageSize="2147483646" />
</binding>
</customBinding>
Before calling the service, we need to set the username and password if needed, e.g. -
ChannelFactory
<ISomeContract> channel = null;
channel.Credentials.UserName.UserName = "MyUser";
channel.Credentials.UserName.Password = "abc123";
Then we can create our channel and call the services, That's it!
Service Side - Extracting the UserName from the ClaimSet:
foreach
(ClaimSet claimSet in ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
{
foreach (Claim claim in claimSet)
{
if (claim.ClaimType == ClaimTypes.Name && claim.Right == Rights.Identity)
{
return (string)claim.Resource;
}
}
}
Notes on top of my mind:
- This was suitable in my case where I searched for a fast and easy approach for replacing the normal windows integrated security.
If you need to pass along more information or manage some sort of identity management, you can use authorization policies to make changes to the claim set, perhaps taking it further and use a custom token (SAML is a good standard) with a trusted issuer and implement a sort of WS-Trust mechanism
- You can extract the caller's username from the ClaimSet, one thing you do lose here over windows integrated is the ability for using windows account impersonation so the actual context of the code to run under the caller's windows identity - you would have to know the user's password and perform an actual impersonation in this case
- When using this mechanism, if the services call other services and the "others" want the initial caller's identity then they should support the same security model or you would need to impersonate the caller's identity on the first service.
- Might think of implementing some sort of a intermediate service which will manage all calls and bridge over security differences in this case