torsdag den 22. september 2011

Implementing Active Federation in a Passive Federation website.

This post is mostly notes for my self. I spend a few hours trying to get this to work so didn’t want to loose it.

I have a running STS that works perfectly with Passive Federation. I provide a GUI where customers can authenticate them self though various social providers like Facebook and linked in, but they can also login using their own STS (mostly ADFS). I needed to offer this though Active Federation too. (user sends a Issue Request Token with a UserNameWSTrustBinding and I need to validate this against all STS providers I have registered for that username )

There is a billion examples on Google on how to do this but I kept getting HTTP error 404 when calling the web service. but after trying hundred of thousand's different web.config setups I finally managed to get it working.

So I create a class that can validate username and password

Imports Microsoft.IdentityModel.Tokens
Imports Microsoft.IdentityModel.Claims
Imports System.IdentityModel.Tokens

Public Class CustomUserNameSecurityTokenHandler
Inherits UserNameSecurityTokenHandler

Private _CanValidateToken As Boolean = True
Public Overrides ReadOnly Property CanValidateToken() As Boolean
Get
Return _CanValidateToken
End Get
End Property

Public Overrides Function ValidateToken(token As System.IdentityModel.Tokens.SecurityToken) As Microsoft.IdentityModel.Claims.ClaimsIdentityCollection

Dim userNameToken As UserNameSecurityToken = TryCast(token, UserNameSecurityToken)
If userNameToken Is Nothing Then
Throw New ArgumentException("The security token is not a valid username token.")
End If

If userNameToken.UserName = userNameToken.Password Then
Dim identity As IClaimsIdentity = New ClaimsIdentity()
identity.Claims.Add(
New Claim(ClaimTypes.Name, userNameToken.UserName))
identity.Claims.Add(
New Claim(ClaimTypes.Role, "NoobsAndMorrons"))
Return New ClaimsIdentityCollection(New IClaimsIdentity() {identity})
Else
Throw New InvalidOperationException("Username/password is incorrect in STS.")
End If
Return MyBase.ValidateToken(token)
End Function
End Class

And then I added these sections to my web.config file
First we need to remove Microsoft's default handler and add the above class


  <microsoft.identityModel>
<service>
<securityTokenHandlers>
<remove type="Microsoft.IdentityModel.Tokens.WindowsUserNameSecurityTokenHandler, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add type="CustomUserNameSecurityTokenHandler" />
</securityTokenHandlers>
<service>
<microsoft.identityModel>

Next we add a placeholder for the web service requests. Add an text file and rename it issue.svc, and add this to it.


<%@
ServiceHost
Factory
="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceHostFactory"
Service
="CustomSecurityTokenServiceConfiguration"
%
>

Next go back to web.config and add this


  <system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract" >
<endpoint address="" binding="customBinding" contract="Microsoft.IdentityModel.Protocols.WSTrust.IWSTrustFeb2005SyncContract"/>
<endpoint address="" binding="customBinding" contract="Microsoft.IdentityModel.Protocols.WSTrust.IWSTrust13SyncContract"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<federatedServiceHostConfiguration />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true"/>
<serviceCredentials>
<serviceCertificate findValue="7A41CF269D6BCDED80DDD9B6FD517E37891453B5" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding >
<security authenticationMode="UserNameOverTransport" />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<system.serviceModel>

Enjoy …I know I didn’t

Ingen kommentarer:

Send en kommentar