It is becoming more commonplace for the means of authenticating a user to be externalized away from the content provider. In federation parlance the content provider is known as the Relying Party (RP) and is so named because it is reliant upon an external entity for authentication, that entity being known as the Identity Provider (IdP). The diagram below depicts this relationship where the RP and IdP are separate entities linked by a trust relationship. i.e – the RP trusts that the IdP can correctly authenticate and assert information about the user (we might expect that the IdP is trusted by several other RP’s or that the RP trusts several IdP’s but this simplest of scenarios is a good starting point from which to evolve the discussion).
The steps towards giving a user access to the RP content are as follows:
End user attempts to access the RP
The RP has no knowledge of the user and instructs the client to send the user off to the IdP for authentication
The user authenticates and the IdP instructs the client to send the user back to the RP with a token (generally comprised of XML but not exclusively so) representing the users identity
The RP validates the token and gives access to the user
In this scenario the client application can either:
- Simply route traffic between the RP/IdP with no modifications
- This is a ‘passive’ client, a good example being a web browser executing GET/POST redirects
- Compose the messages based upon metadata served up by the RP/IdP
- This is an ‘active’ client, one example being an browser control that sends SOAP messages into the RP/IdP based upon the published policies
Here is a more comprehensive description of active and passive clients.
What follows is a demonstration of how WIF trivialises the effort required to mediate between RP/IdP using the WS-Federation passive profile.
You will need the following installed:
- Visual Studio 2008/2010
- .NET Framework 3.5 SP1
- Windows Identity Foundation RTW
- Windows Identity Foundation SDK
Create a simple Relying Party application for sending requests
1. Create an ASP.NET web application called WIFRelyingParty with the following attributes:
- Accessible at http://localhost/WIFRelyingParty
- Has a basic web page called Content.aspx
- Has references to Microsoft.IdentityModel.dll and System.ServiceModel.dll
- Has an assembly name and default namespace of ‘WIFRelyingParty’
2. In the Page_Load event handler for Content.aspx.cs, insert the following code (you will need to add the using directives yourself):
- IdP endpoint– where the signin request is going
- RP realm– identifies the RP to the IdP
- Reply address– the url that the IdP should redirect the browser back to
Here is a snippet of what the IdP recieves:
Create a simple Identity Provider application for processing requests
1. Create an ASP.NET web application called WIFIdentityProvider with the following attributes:
- Accessible at http://localhost/WIFIdentityProvider
- Has a basic web page called Login.aspx
- Has references to Microsoft.IdentityModel.dll, System.IdentityModel.dll and System.ServiceModel.dll
- Has an assembly name and default namespace of ‘WIFIdentityProvider’
2. Add a new class to the project called CustomSecurityTokenService.cs and overwrite it with the following code:
NB - You will need to add a certificate (public and private keys) to the local machine personal store and replace <certificate subject> with the correct name. You may also have to assign permissions to the private key of the cert for the identity that your website is running under.
4. Add the following helper method to Login.aspx.cs:
OK, so what have we achieved? The only bits of real relevance are steps 2 and 3. In step 2 a custom Security Token Service (STS) has been created simply by deriving from the SecurityTokenService base class and overriding a couple of methods. The GetScope method allows us to define the certificate that will be used to sign the token (so that the RP can verify the token has not been tampered with and also that it is from the targeted IdP). It also allows us to define a certificate for encrypting the token (using the RP public key with the private key held at the RP for decryption) but I have set this property to false for now so that we can see the clear text token.
A common mistake
“A SAMLAssertion requires at least one statement” ……………. What’s this!?
Ok I have been a bit naughty but I wanted to demonstrate an error I have hit time and time again when trying to shortcut prototypes. The clue as to why this occurs is in the SAML1.1 assertion schema, specifically the following:
The SAML assertion created by the IdP MUST contain at least one Attribute (i.e – a claim) and rather than WIF saying as much, it reports that the entire AttributeStatement is missing. Trust me, if you use WIF or ADFS v2 you WILL eventually get careless and hit this one.
The remedy is easy, just modify the GetOutputClaimsIdentity method to return something substantial like the following:
Extend the Relying Party application to handle responses
1. Overwrite the contents of the Page_Load event handler for Content.aspx.cs with the following code:
This post demonstrates that it is possible, using WIF, to implement simple Relying Party (RP) and Identity Provider (IdP) applications using very few lines of code. It goes without saying that this is not production-ready code but it serves to highlight the important points.
Thus far this has all been achieved programmatically. However, in the true WCF spirit (upon which WIF is built) it is possible to achieve the same results using configuration and reduce even further the lines of custom code. In the next post I will be demonstrating this and also how we can tighten up the security of the RP/IdP applications.
Written by Bradley Cotier