In the following example i will show how to build an Identity Provider also called a passive security token service (IP-STS) that issues tokens using WS-Federation. This post builds on work done in a previous post, Create your own active STS. In this article I will show how to create a complete working example of an Identity provider (IP-STS). The code for the the passive sts skeleton with full source is downloadable from here.
The image below covers all the elements that I am currently aware of when dealing with WIF using WS-Trust & WS-Federation. See the following post for definitions about the WIF terms.
Solution overview
On the left you can see the overview of the solution. I have defined the solution into folders to make it easier to follow.
The folder dealing with the WS-Trust is where all the hard work happens. This is where the user actually gets authenticated and where the 1st token is generated. I will not be going into detail about the Active STS. I suggest you follow the older post about the creation of a active STS for more information.
The WS-Folder contains 2 websites. The PassiveSTS is the identity provider where the user logs on. The PassiveClient is a website that is enrolled into Federation and trusts the token provided by the PassiveSTS. I will briefly show the client but for more information relating to the integration of a client website with a passive sts please see one of my older posts that deal specifically with the integration with a passive sts.
The Active STS
Below is a screenshot of what the active sts looks like when run. See creating your own active STS for more information.
An active client using the active STS.
The Passive STS
Below is a screenshot of what the passive sts or IP-STS looks like in the sample that I have provided. When the client tries to browse to the passive client he will be redirected to the passive sts by the WSFederation module.
Things to take note of:
- All certificate validation is turned off in this sample. This is because the localhost certificate used by IIS is self signed and cannot be verified. This is something that you would need to enable in a production environment.
- I am running on a https port of 444. This is purely for development purposes and can be configured to be anything.
- To run this sample the host that is hosting the active sts needs to be up and running first. Use the provided active sts client to make sure it is configured and working properly.
- I have provided the hard coded password from the Active STS as a hint on the website.
There is actually not really much to a passive STS, as i stated elsewhere most of the work is done in the active sts.
Let’s look at the web.config.
As you can see the only additions are the configuration sections, the app settings and
<?xml version="1.0"?> <!-- For more information on how to configure your ASP.NET application, please visit Identity configuration. http://go.microsoft.com/fwlink/?LinkId=169433 --> <configuration> <configSections> <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" /> </configSections> <appSettings> <add key="ActiveSTSUrl" value="http://localhost:1701/TokenService"/> <add key="IssuerUri" value="https://WCB:444/PassiveSTS/" /> <add key="TokenAudienceUri" value="http://localhost" /> <add key="CertificateSubject" value="CN=localhost"/> <add key="CertificateDnsIdentity" value="localhost"/> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> </system.web> <system.identityModel> <identityConfiguration> <certificateValidation certificateValidationMode="None" /> </identityConfiguration> </system.identityModel> </configuration> <add key="ActiveSTSUrl" value="http://localhost:1701/TokenService"/> <add key="IssuerUri" value="https://WCB:444/PassiveSTS/" /> <add key="TokenAudienceUri" value="http://localhost" /> <add key="CertificateSubject" value="CN=localhost"/> <add key="CertificateDnsIdentity" value="localhost"/> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> </system.web> <system.identityModel> <identityConfiguration> <certificateValidation certificateValidationMode="None" /> </identityConfiguration> </system.identityModel> </configuration>
- The ActiveSTSUrl is the location where the active sts is running. This location can be configured in the configuration of the active sts. Please see the article – creating your own active sts.
- The IssuerUri is the uri of the passive sts’s own location.
- The TokenAudienceUri is used to by the Active STS to generate a token that will only be usable by the party whose Uri is specified here.
- CertificateSubject is the Common Name of the certificate to be used when signing the issued token. Often STS sites have a different certificate for the https protocol and the signing of the token.
- CertificateDnsIdentity is used to provide the STS with the actual name of the server. The active STS will try and do a reverse lookup on the party doing the request to confirm if the requester is who he says he is buf often on developer machines this is not possible. Example my url for this sample is WCB and not localhost, so the reverse lookup will fail for WCB.
The passive STS sign-in code.
The code below is the heart of the passive sts. The passive STS does a sign-in request with the active sts that then returns a token. This token contains the authenticated identity. Next the token is passed to the Federation module and a federated cookie is generated and the user is redirected back to the requesting website.
protected void lnkBLogin_Click(object sender, EventArgs e)
{
SessionSecurityToken token = null;
if (!ActiveSTSProxy.Proxy.SignIn(TxtUserName.Text, TxtPassword.Text, out token))
{
lblError.Text = “The provided credentials are invalid. Please verify and retry.”;
}
else
{
LogUserIntoFederation(token);
}
}
public static void LogUserIntoFederation(SessionSecurityToken token)
{
if (token != null &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; token.ClaimsPrincipal != null &amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp; token.ClaimsPrincipal.Identity.IsAuthenticated)
{
HttpContext.Current.User = token.ClaimsPrincipal;
var config = TokenService.GetSTSConfiguration();
var requestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromUri(HttpContext.Current.Request.Url);
TokenService securityTokenService = new TokenService(config);
SignInResponseMessage responseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(requestMessage, (System.Security.Claims.ClaimsPrincipal)HttpContext.Current.User, securityTokenService);
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(responseMessage, HttpContext.Current.Response);
}
}
The passive client
Once authenticated the user will be redirected back to the client website. This client is technically called the replaying party or RP. For sake of completeness i have created a client website that integrates with the passive STS. When a user is authenticated the client website I created lists the claims provided in the token. The client also has the ability to sign-out of federation.
The “magic” of federation is all done in the web.config configuration file of the website. Integration with a passive sts is discussed in the following article. The code to sign out of federation can be seen below.
protected void LnkSignOut_Click(object sender, EventArgs e)
{
Uri issuerUri = new Uri(FederatedAuthentication.FederationConfiguration.WsFederationConfiguration.Issuer);
Uri repleyUri = new Uri(FederatedAuthentication.FederationConfiguration.WsFederationConfiguration.Reply);
WSFederationAuthenticationModule.FederatedSignOut(issuerUri, repleyUri);
}
To secure your STS make sure to look at the following posts as well.
Securing Http with HSTS in IIS
How to disable insecure cipher suits
Enable secure cookies over HTTPS.
Enjoy, and I would like to hear if you have any questions.