First things First
If you are looking for an article that shows a lot of code and dissects the new WIF 4.5 APIs, then you won’t find what you need here.
My aim in this article is to explain the “why” and the “what” rather than the “how”. Once you understand that, the “how” becomes really simple. This article does not assume pre-knowledge of the topics of federation, claims, and WIF so it’s suited for beginners. However, I think that mid-level knowledge audience will also benefit from it. If you’re like super-expert, well please contact me to help me in my current project.
What Exactly is the Problem?
Authentication (and authorization) is an ever present challenge for most applications. The challenge that these applications face is the same: authentication logic creeps into the application code and becomes coupled with it; any change to the authentication requirements will result in a change in the application itself.
Say for example that your user store is SQL Server and new business mandates adding an existing Oracle-based user store to your list of users, or maybe you want to mix your authentication to support both custom user stores (SQL Server or Oracle) with Active Directory user store. And what about social media? It’s increasingly popular nowadays for applications to allow authentication via services such as Google and Facebook.
Here is another tough case: assume you used to ask you users for username/password combination to log in. Now based on certain needs, you want them also to supply additional information such as a one-time code. This will certainly lead to UI change for your login page as well as code change.
In all these cases, something has to change in your code. Of course, having a good architecture with a proper separation of concerns will ease up the change. However, the idea is that you still have to manage this authentication logic instead of focusing on the business side of your application.
Claims-based authentication is the architecture that solves this problem.
Claims-Based architecture allows you to delegate authentication logic into another entity. This entity is a “some” layer which abstracts all authentication related coding and gives your application what it needs: is the user authenticated or not, and some information about the user (called claims or assertions) that lets your application take authorization decisions.
The claims-based architecture defines the following actors:
- Subject: the entity that needs to be authentication. This can be a user that wants to log in to your application, or a piece of code in your application that wants to access a web service.
- Relying Party (RP): the application (in case the Subject is a user) or the web service (in case the Subject is application code) that needs to delegate the authentication logic
- Identity Provider (IP): the entity (that “some” layer mentioned before) that actually holds the authentication logic. The IP talks to the user stores as appropriate and performs actual authentication.
- Claim: When an IP performs successful authentication, it returns to the RP a set of claims. Claims are statements about the authenticated entity – for example birth date, department, role, etc… – that gives the RP information to take authorization decisions.
- Token: Claims travel inside a token. Although a token can be a username/password combination or even a simple string such as bearer token in OAuth 2.0; in this context tokens can be either XML-based such as SAML tokens or binary-based such as X.509 certificates.
In addition to the above definitions, WS-Federation and WS-Trust protocols define another term called Secure Token Service (STS). STS is the web service exposed by the IP that provides the authentication service.
Before the claims-based flow can start, the RP and IP need to publish their policies. In abstract terms, a policy is a contract published by an entity that specifies the terms and conditions that other entities must obey before establishing communication.
In this context, the policy published by the IP specifies the supported protocol(s) and security requirements as well as supported claim types. Similarly, the policy published by the RP specifies its own protocol, security, and claims requirements as well as the list of IPs it trusts to delegate authentication to.
The rest of the article discusses WS-Federation (and related WS-standards) and its implementation in WIF, while I will also briefly discuss SAML 2.0.
The WS-* Mania
For some, the WS-* standards are something to avoid. They tend to strike developers as being overly complex. Indeed complex they are. However, with the advent and continuous enhancement of developer libraries, most of the times working with WS-* standards is nothing more than configuration tweaking. Granted however, you always need to understand what is going behind the scenes if you really want to understand the architecture.
This section discusses – briefly – some core WS-* standards that are related to WS-Federation.
WS-Security is a SOAP extension that adds authentication/authorization, message protection, and message integrity to SOAP messages.
- Authentication/authorization: authentication is implemented using security tokens while claims carried inside a security token aid in authorization. Although can be extended, the three types of tokens you’d usually see are Username, Binary, and XML-based tokens.
- Username tokens: these are the plain-old username/password combinations sent in the SOAP header. Verification of identity can be achieved by hashing the password or applying a digital signature.
- Binary tokens: these usually come in two flavors: X.509 certificates and Kerberos tickets.
- X.509 certificates: an X.509 certificate is the public key container of a public/private key pair. Obviously since it contains a public key it cannot be relied upon for authentication by itself. The certificate is signed with the private key portion of the sender. The receiver uses the public key to verify the signature. Since the private key is unique for the sender, signature verification proves identity
- Kerberos tickets: if a Kerberos infrastructure is already in place, WS-Security recognizes Kerberos tickets as a valid security token type
- XML-based tokens: XML tokens were published as an ad-on specification to WS-Security. XML tokens contain a set of claims about the sender. Similar to X.509 certificate tokens, XML tokens must be accompanied by a signature generated by the sender so that the receiver can verify its identity. Probably the most dominant form of XML tokens is SAML token.
- Message protection: Whereas at transport level message protection is established using SSL, at message level this is done via XML Signatures. Depending on the configuration, WS-Security uses either a symmetric shared key or an asymmetric public/private key pair to encrypt the required message content. In the symmetric approach the shared key must be exchanged securely prior to communication. In the asymmetric approach the sender encrypts the (required) message content using the receiver’s public key and the receiver decrypts it using its private key. Most of the time though, the approach used is a combination of both due to the fact of asymmetric approach being compute-expensive. In this hybrid approach, asymmetric encryption is used to exchange a shared key and then this shared key is used for encryption for the rest of the session communication.
- Message Integrity: as discussed in the authentication section, XML signatures are used to establish user identity. It is also used to establish message integrity; i.e. that the message has not been tampered with. By attaching a signature with a message, the receiver recalculates the signature and verifies integrity if both signatures match. Similar to encryption, a hybrid approach is usually used to reduce the cost of asymmetric-based signatures.
WSDL does a good job describing basic web service requirements such as message schemas and authentication headers. However, WSDL cannot describe contractual requirements such as security. For example, recall form the previous section of Claims-based architecture, that an RP-IP interaction is governed by a set of security policies. These policies cannot be described using WSDL; instead they are described by WS-Policy and its related specification WS-SecurityPolicy.
In general, there are WS-Policy assertions for security, reliable messaging, sessions, transactions, reliable messaging, among others. In WCF, these policies are specified either as code attributes or configuration sections.
- WS-Policy: a specification that defines a framework for describing policy assertions. An assertion is a requirement or preference of the service. This specification defines a common language regardless of the assertion domain (security, transactions, reliable messaging, etc…).
- WS-PolicyAssertion: a specification that defines general messaging-related assertions for use with WS-Policy. Separate assertions exist for different domains; for example, WS-SecurityPolicy, WS-AtomicTransactions, and WS-ReliableMessaging.
- WS-PolicyAttachment: a specification that describes how policies are attached to WSDL (and UDDI).
WS-Addressing specification provides elements that enable end-to-end transport-independent message transmission. For example this allows you to implement message routing (previously WS-Routing) where – based on some message criteria – you can explicitly specify the next hop in the message route. Also some of the other things that you can do is specify a different response or fault return URLs to a message and thus sending the response to a different endpoint than the originator.
As discussed in the claims-based architecture, you can delegate your application authentication logic to another entity which issues claims that your application. The part I skipped is how to make your application “trust” these claims? What prevents a fake IP from generating a claim and sending it to your application which then will grant him access?
Let’s take this one step further: assume two companies A and B want to conduct business. Company A want company B users to access its application. How can this be done? One way is for A to provision B users; however, this clearly is a troublesome solution as A will have to manage and control B users. Wouldn’t it be a much better solution if we make A “trust” B users without actually managing them?
WS-Trust is a specification that tackles the above two scenarios. WS-Trust introduces the concept of a Secure Token Service (STS), which is a web service that is responsible of generating claims that are trusted by consumers. In the first scenario (authentication delegation), you have your application establishing a WS-Trust relationship with an STS service for an IP. In this second scenario (companies A & B), both parties establish a WS-Trust where A trusts an STS for B IP; this way B users can carry tokens issued by their IP-STS and present these tokens to A, which trusts the STS and thus grants access.
WS-Trust defines a message request called RequestSecurityToken (RST) issued to the STS. STS in turn replies via a response called RequestSecurityTokenResponse (RSTR) that holds the security token to be used to grant access. WS-Trust describes the protocol for requesting tokens via RST and issuing tokens via RSTR.
WS-SecureConversation specification provide a mechanism to improve a service response time when the client engages with a lengthy communication with that service.
When a client sends a message to a secure service, part of the request will be dedicated to credential negotiation and authentication. At transport level, this is accomplished in SSL handshake process so any consequent requests use the secure session already established. WS-SecureConversation achieves the same on the message level.
WS-SecureConversation specification states that the client first sends an RST (from the WS-Trust specification) to the service. The service validates the credentials within the RST and issues back a token called Secure Context Token (SCT) with a symmetric key to perform the cryptographic operations for the remaining communication.
These tokens are used by WS-Security for authentication and integrity and are described at both ends (IP & RP) using the WS-SecurityPolicy assertion.
So we’re finally at the WS-Federation section! All the previous specifications discussed lead to this place.
Let’s start by defining federation: Federation refers to multiple security domains (also called realms) – typically multiple organizations in B2B scenarios – establishing trust for granting access to resources. Carrying on with the terminology we have been using, an RP in domain A can trust an STS IP in domain B so that B users can access resources of A.
WS-Federation build on WS-Trust and simplifies the creation of such federated scenarios by defining a common infrastructure for achieving federated identity for both web services (called active clients) and web browsers (called passive clients).
WS-Federation says that organizations participating in federation should publish communication and security requirements in Federation Metadata. This metadata adds federation specific communication requirements on top of the WS-Policy (and WS-SecurityPolicy) metadata described before. For example, token types and single sign out requirements are examples of what is defined in the Federation Metadata.
WS-Federation does not mandate a specific token format, although as we will see later, SAML tokens are used heavily.
Identity and Access Control in .NET 4.5
Identity and Principal pre-.NET 4.5
If you have been creating applications in .NET framework since v 1.0, chances are you have already came across interfaces
IIdentity would represent the identity of the authenticated user while
IPrincipal contains that specific identity in addition to a method to check if the user is a member of a certain role.
Different implementations existed for
WindowsPrincipal are used for windows, active directory, or Kerberos authentication
GenericPrincipal are used for custom authentication such as forms authentication
As you can see, role-based access (or authorization) up until .NET 4.0 was really restricted to the
IsInRolemethod of the
IPrincipal and its implementations. There are multiple ways to call this method; you can call it directly via the API, or you can use attribute-based authorization (
PrincipalPermission), or you can use the authorization element in the web.config. Regardless of the method, your role-based access power was limited to checking if the logged in user belong to a certain group or not.
Now if you have reached so far in this post, you will for sure have noticed that claims-based authorization gives you much bigger power. Using claims you can make access decisions based on things like a user birth date, national id, and of course roles, among others. The idea is that the system that performed authentication (the IP in our literature) attaches any attributes agreed with the RP as a set of claims (assertions); the RP then uses these claims to make suitable authorization decisions.
So are claims not supported pre-.NET 4.5? Yes they are, and here’s how:
WCF 3.0 Claim Transformation
Before Windows Identity Foundation (WIF) 1.0 was shipped, Microsoft’s first attempt to incorporate claims into their security model came under the umbrella of WCF. In WCF 3.0 Microsoft included the System.IdentityModel assembly which basically generated a set of claims for every security token authenticated by WCF. WCF 3.0 shipped with the following classes:
System.IdentityModel.Claims.DefaultClaimSet, which represents any additional generic claims sent to the service
System.IdentityModel.Claims.X509CertificateClaimSet for converting X509 tokens to claims
System.IdentityModel.Claims.WindowsClaimSet for converting Windows tokens to claims
WCF 3.0 included authorization policies to perform the actual claim transformation.
The problem in this approach was that now .NET developers have two completely different security infrastructures for web applications (
IPrincipal) and for WCF services (
System.IdentityModel). So if you have an application which consists of both web app and web service, then you’ll have to write nearly the same code twice against two different libraries.
Microsoft enhanced their claim infrastructure in In WIF 1.0. Instead of the System.IdentityModel used in WCF 3.0, they shipped a new assembly of name Microsoft.IdentityModel.
The need to support claims was achieved by adding another implementation of
IClaimsPrincipal which will be populated once claims-based authentication is used. As you can see, this way WIF combined both worlds: that of base classes
IPrincipal and that of WCF 3.0 claims infrastructure.
Here is how you would retrieve claims for a claims-authentication enabled application:
| Copy Code
IClaimsIdentity identity = Thread.CurrentPrincipal.Identity as IClaimsIdentity;
string email = (from c in identity.Claims where
c.ClaimType == System.IdentityModel.Claims.ClaimTypes.Email
As you can see, we’re casting the current principal’s identity to get the
Now even with this improved approach, can you already spot the drawback? Well the issue here is that with this approach if you use
GenericPrincipal you won’t get claims as
IClaimsPrincipal is just another implementation of
IPrincipal much like the other two. It’s either this or that. This makes claims support in .NET 4.0 not a first class citizen.
Identity and Principal in .NET 4.5
In .NET 4.5 claims are made available regardless of the authentication type. What Microsoft did was creating a new implementation of the base
ClaimsPrincipal. Then they made every other principal (
GenericPrincipal) derive from
ClaimsPrincipal, and they removed the
IClaimsPrincipal of .NET 4.0. This way, you will get claims all the way; for example even if you use forms authentication, all the attributes you pull from a membership provider will be carried in claims.
This way, role based access is unified for all authentication types and more important, it’s much richer than the simple
IsInRole approach because you now depend on claims to take decisions.
Let’s see how you can retrieve claims for a claims-authentication enabled application and compare this to the same code you had to write pre-.NET 4.5:
| Copy Code
string email = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
ClaimsPrincipal.Current basically plays the same role that
Thread.CurrentPrincipal used to play.
Let’s see the new claims-based model in .NET 4.5. Below you can see the debugger of a VS 2012 web application using
You will notice that the base class is of type
System.Security.Claims.ClaimIdentity which as explained is the new base class for the identity classes as of .NET 4.5. Also notice how although we used windows identity, claims are populated with windows login specific information. In .NET 4.5, you will get claims no matter what.
The below figure shows a similar result when we define a
GenericIdentity (simulating a forms authentication for example). Again the base class is common and a claim of type name is generated by default:
When using forms authentication, you will get the Name claim by default. You can get additional claims by using the ASP.NET Role Manager.
Let’s briefly discuss some more concepts and capabilities of .NET 4.5 claims model.
Supported Credential Types
As discussed before, the biggest advantage of the claim model is that regardless of the authentication mechanism used, your application will always rely on claims to achieve authorization. So your application logic does not really care about the actual type of the security token that was used for authentication; authentication logic is a separate concern with its separate module, your application gets claims and you use these claims to take authorization decisions.
Now this authentication layer I am talking about, can be part of your application itself living in a separate module, or – as discussed in the very beginning – can be a separate STS that your application trusts in the IP/RP model. In this discussion our focus is on .NET 4.5 so authentication will be part of the application, the next section dives into WIF 4.5 where you will see STS in action.
So, you .NET 4.5 application can use any of the following security tokens:
- Forms authentication
- Client certificates
- SAML tokens
- Other extended token types
Once the authentication layer is passed, your application will get claims in the
ClaimsPrincipal shown before.
Before the claims actually hit your application, it can be subjected to a transformation/validation layer. Once example of transformation need is that you know claims will come is a certain format and you would like to change this format to suit your application coding. An example of validation is – say your application accepts claims from an STS – and you want to make sure before handing the claim to your code that the minimum set of required claims are actually present.
To implement this transformation/validation, you will have to override a class called
The logic you wrote in the
ClaimsAuthenticationManager derived class can be run at each and every request, or you have the option to cache its outcome if you believe its logic is expensive. The cached value can be saved in cookies for ASP.NET applications and using WS-SecureCoversation for WCF services.
Finally we are the stage of actually performing authorization decisions based on the claims. The class
ClaimsAuthorizationManager is what you’d want to derive from to implement your authorization logic. This class contains the method
CheckAccess which can be called whenever you want to make an authorization decision.
This way you won’t mingle authorization logic directly into your business logic (which typically was the approach used in the days of the
Once again, I want to remind you that this approach of using claims inside your application is the same regardless if whether the claims are generated by authentication logic as part of your application or if the claims are given to your application by an STS that it trusts. In both cases, you have the ability of using the
ClaimsAuthorizationManager to minimize the coupling between your business logic and the authorization decision.
One final note: the claims-based model is the same for web applications and WCF services. So the .NET 4.5 code to retrieve, transform, and authorize claims works the same regardless of whether the consumer is a .NET 4.5 web app or WCF service.
Windows Identity Foundation (WIF) in .NET 4.5
In the previous section I discussed the claims model in .NET 4.0 vs. .NET 4.5 and showed you how claims are now first class citizens in .NET 4.5. However, the previous section still used the “traditional” authentication mechanism where authentication is still your application’s responsibility. Be cautious though, I do not want the previous section to deviate your attention from the main focus of this article: delegating authentication responsibility to an external entity.
WIF is Microsoft’s technology for encapsulating the inner workings of WS-Federation (and WS-Trust) behind a .NET library which makes it easy for developers to create claims-based apps without the need to know the details of the specs we discussed previously.
As was discussed in the previous section, we have seen how identity and access support in .NET passed through multiple stages, from the simple
IsInRole checking, to claims support in WCF 3.0, to WIF 1.0 and then to .NET 4.5.
WIF 4.5 is where this ends (and the new work begins!). In .WIF 4.5, Microsoft did yet another naming change to the assemblies:
WIF in Action
VS 2012 provides you with the tools to quickly set up your RP and use a local STS. Creating an STS should be really the last thing that you would try to do. However, you will only use this STS for development/testing purposes. Running an STS is not a simple task as its business critical and relies on complicated protocols and cryptographic operations.
STS commercial products are available and you are likely to use them. Some of these products are:
- Active Directory Federation Services (ADFS) v2
- IBM Tivoli Federation Manager
- Oracle Identity Manager
ADFS v2 is the topic of the next article.
So why does Visual Studio give you this local STS? Simply to aid you during the development (and possibly testing) phase where the STS product might not be accessible to you. Since your RP does not hold the authentication logic anymore, all what you have to do before going to live is to edit the policy for your RP to trust the new STS instead of the one created using visual studio.
Create a new VS 2012 ASP.NET 4.5 web forms application. Right click the project and select “Identity and Access”. This will display a wizard giving you three options: ADFS2 and ACS will be discussed in future posts, I will just quickly note that ADFS2 is the STS of AD and ACS is the STS on Azure.
Select the option to create a local STS. In the Local Development STS tab, you can select the SAML token version to use, the local port of the STS, but most important you can select the claims that the STS will give your RP. In WIF 1.0, you had to manually edit the local STS code to change the set of claims; this way is much cleaner and true to the promise of isolating you (the RP owner) from the authentication logic. Notice that you can use from the many pre-defined claim namespaces and you can define your own. Accept the defaults to close the wizard.
VS 2012 has now equipped your RP to trust a local STS and set up the policy between them. To see this, let’s examine the web.config of the RP:
- Forms Authentication removed: your RP now is neither windows nor forms authentication-base. It is a claims-based application, so forms is disabled because forms is the default when creating a VS web forms app.
- Two HTTP modules that makes WIF magic possible:
WSFederationAuthenticationModule: this module intercepts incoming requests and redirect unauthenticated ones to the trusted IP(s). For authenticated requests it processes claims within the security token and presents them to your application in a consumable format.
SessionAuthenticationModule: this module takes care of session management after an authentication is established. The
WSFederationAuthenticationModule module is bypassed and
SessionAuthenticationModule handles requests until the session is expired or a sign-out flow is invoked.
audienceUris: lists the URIs that your RP will consider valid for the received tokens
trustedIssuers: the list of trusted IP certificates that the RP will accept signatures from to verify the token
wsFederation: configures the WS-Federation protocol, such as using the passive protocol flow, the IP that the protocol will talk to, and the realm which is basically the ultimate return-URL that the protocol flow will end up in – the RP itself in this case.
In addition, VS 2012 has created a FederationMetadata.xml file in the RP solution. Recall from the discussion of WS-Federation that organizations participating in federation should publish communication and security requirements in Federation Metadata. This XML file holds these requirements for this RP.
Now run the application, quickly notice the browser navigation and you will see that your application gets redirected to the local STS which performed the (hardcoded) authentication and returned back to your application as an authentication user (assume you’re Terry for a moment!). You can now access the claims inside your application just like we have seen before.
Now let’s see what happened in the background to examine WS-Federation and the supporting protocols discussed before in action. To do so, I will use Fiddler:
Step 1: A user browses the RP
You asked for the application via the browser. The WIF HTTP module
WSFederationAuthenticationModuledetects that you are not authenticated, so it redirects the browser back with a 302 response and with a Location header that contains the address of the IP-STS at which you must authenticate. In addition, a set of WS-Federation protocol query strings are also supplied to govern how the flow will behave:
- wa: with a value of wsignin1.0 which means that this is a sign in request (note that WS-Federation also supports sign out flow, so this parameter is mandatory)
- wtrealm: this is the RP itself, and it represents the intended consumer of the token
- wct: this is an optional parameter that specified the time of the response of the RP. This might be used as indication to possible attacks if the IP sees that there is a time lag between this parameter value and the actual time it received the sign in request
Step 2: The browser sends a GET request to the STS
The browser then uses the STS address in the Location header and the query strings discussed before to assemble a sign in request to the STS. Here is the request made to the local STS:
Step 3: The IP-STS performs authentication
In “real” scenario, the STS will normally present you with an authentication form that you would supply your credentials to. This procedure of STS authenticating users – as mentioned before – is outside the scope of WS-Federation and thus WIF. The STS can authenticate you against an AD, a custom user store, or even using an X.509 certificate. This depends on the type of the RP application and where the users are coming from. Regardless of the mechanism to authenticate, the STS will – assuming successful authentication – generate a security token containing the claims agreed between the IP and RP via policy.
Step 4: The STS sends the response back to the browser
The STS sends back to the browser a hidden form with will POST back to the RP. The form contains the following information:
- wa: same as before indicating a sign-in flow
- wresult: contains the SAML security token issued by the STS.
If you carefully examine the response, you will see many of the protocols discussed before coming into play:
RequestSecurityTokenResponse (RSTR) of WS-Trust carries the token collection
- XML Signature of WS-Security is used to provide message integrity and trust between the IP and RP
- WS-Policy – driven by the Federation Metadata – indicates rules such as token lifetime
- WS-Addressing is used to identify the endpoint reference for the passive request (i.e. the RP)
I reformatted the content for ease of display, here you can see these protocols in action:
Note: There is a difference between SAML-P (the protocol) and SAML token. SAML-P is a full blown protocol much like WS-Federation. SAML token is a token type that can be used independent of SAML-P, and it’s one of the token types frequently used in WS-Federation.
I will briefly touch on SAML-P 2.0 at the end of this article.
Step 5: The browser posts back to the RP
The browser uses the hidden post form from the previous step to post the result shown in the previous step back to the RP
Step 6: The RP verifies the token
Verifying a token involves multiple checks that could take place based on each situation and policy. Some of these checks are:
- Integrity: in case digital signature is used, the RP uses the IP public certificate included in the request to verify that the digital signature is valid
- Expiration: in case an expiration for the token is present, the RP verifies that the token is not expired
- Decryption: in case encryption is used, the RP uses its private key to decrypt the contents. In the above example, encryption was not used as we were in the passive (web browser) case, later I will discuss the active case and illustrate the difference.
- Source: using the policy, the RP makes sure the token is issued by a trusted IP
- Claims: also using the policy, the RP checks that the set of claims issued are the ones agreed on
Step 7: A session cookie is issued
Once the token is verified, the RP issues a session cookie back to the browser so that next requests do not pass through the same WS-Federation process.
WIF for Active Clients
The browser-based scenario we have just seen is called a passive scenario. Passive clients are those that do not possess the WS-* capabilities. Browsers are passive because they just perform redirects they are told to, but by themselves browsers have no notion of WS-Federation.
Another type of clients are active ones. Active clients are those that can perform WS-* operations; an obvious example are WCF services. A WCF service can also act as a claims-based enabled RP. In this scenario, the client (the Subject as per the defined terminology) is an application calling the WCF service which requires claims-based authentication from a trusted STS.
The full cycle goes as follows:
- An application reaches a line where it is invoking a WCF service. The WCF service itself is an RP configured for claims-based authentication.
- The WCF client library at the application finds out that the WCF service needs a security token to grant access. The library then issues an RST to the STS.
- The STS replies back with a security token via RSTR
- The client application then uses this token to access the WCF service. Now here you can spot a major difference between the passive and active scenarios. Recall in the passive case that the client (browser) had only Https as option for encrypting its request to the RP – called transport level. In the active case, the client (application) can actually use the token to perform custom message level encryption on the message. Message level security has the benefits of better performance as we can be selective for which parts of the message are deemed sensitive and thus to be encrypted and it also supports end-to-end messaging.
The good news is that when it comes to WIF, you do not have to learn anything new than what you saw in the passive case. The same programming model applies. Again you can right click a WCF project in VS 2012 and configure it as an RP using the “Identity and Access” wizard. The defining difference between active and passive clients becomes clear when you inspect the web.config of the WCF service; you will see the ws2007FederationHttpBinding in use, which again shows you that active clients are WS-* aware.
So far the discussion has been centered on one role that STS can play, and that is issuing claims on behalf of an IP; and thus it has been called an IP-STS. However, an STS can play another roles; the role of a Federation Provider.
Let’s recall the scenario I discussed before of the two companies A and B wishing to enter a federated business agreement. In that scenario I gave an example of B users needing to access a (single) application in A and how that application is configured as an RP for an STS in B.
Now let’s extend the scenario a bit: instead of B users wanting to access a single application in A, both companies want to extend their partnership and now B users must be able to access multiple A applications. Under the role of IP-STS we have discussed so far, every A application must establish trust with B IP which in turn must provision every A application.
A far better solution is for A to expose a Federation Provider. A Federation Provider is a Resource STS (R-STS) that sits on the resource side (on the relying party side – A domain in this case). Company A applications then establish trust with the R-STS and B then provisions this STS only.
A typical flow will then goes as follows:
- An employee on B domain tries to access an A application
- A detects (via WIF for example) that the user is not authenticated and redirects the request to the STS it trusts; in this case it’s the R-STS on A’s domain
- In its turn, the R-STS is configured to accept tokens from B IP, so the request is redirected back to B IP
- The user authenticated herself again B IP using any mechanism defined by B
- A request is submitted to the R-STS on A containing the token
- R-STS processes the request and typically does one of 3 things:
- Issue claims exactly as they were sent from B IP. Here the R-STS decides that the included claims satisfy A application needs
- Modify claims based on some rules, for example to satisfy special formatting needs for A applications
- Add new claims that the R-STS knows are important for A applications yet B IP had no information about. For example R-STS might maintain some information from previous transactions for a specific user.
- The resulted token is then sent to the originally request A application which grants access
Once again, using WIF you can create your own local R-STS; although as explained before, in real scenarios you would go with commercial products. ADFS v2 is also suited to play the role of R-STS; for example its claims-transformation language is ideal for claims modification. Another great example is Azure Access Control Service (ACS) which also plays the role of a Federation Provider on the cloud.
Both ADFS v2 and ACS will be discussed in future articles.
I will close this article by briefly addressing SAML 2.0. Please note that I have never implemented this protocol myself, rather what I present here is a summary answer for the common question of WS-Federation vs. SAML just to get you going; but you’ll have a lot of reading to do if you want a definitive answer.
SAML 2.0 consists of two parts; a protocol (much like WS-Federation) that defines interactions and supported communication protocols, and a token format – conveniently called SAML token. The token specification is separate from that of the protocol, so you can use the token in another protocols. Actually that is what we have been doing in this article all along by using SAML tokens to carry claims in the WS-Federation protocol.
From a very high level point of view, SAML 2.0 protocol (SAML-P) achieves the same objectives of WS-Federation: it allows business partners to enter a federation agreement and allows delegation of authentication logic from an application (Service Provider) to an external entity (Identity Provider). The Identity Provider creates a SAML assertion that the Service Provider then validates to grant authentication. The SAML assertion is a SAML token containing claims.
SAML specification is actually divided into multiple parts:
- SAML core: this specification defines the structure of the SAML assertions and the supported protocols. You can think of this as the base of every other specification
- SAML bindings: each of the protocols described in the core specification is detailed in the binding specification where each binding has certain communication and formatting requirements
- SAML profiles: the profiles specification puts together the different specification into a usage profile, such as the login and logout profile.
- SAML metadata: this specification is basically what makes SAML-P tick. It defines the agreement requirements between the Service Provider and the Identity Provider to establish SAML-P (supported bindings, certificates, cryptography, etc…). Basically this is to SAML-P what WS-Trust is to WS-Federation.
WIF does not support SAML-P, although some time ago an extension to WIF that adds SAML 2.0 support was CTP’ed but has not took off since then. Here you can see the announcement:
It’s not all bad however, ADFS 2.0 however fully supports SAML 2.0 protocol. Why is this great news? Well simply because of the range of interoperability scenarios that is now possible between two environments one adopting WS-Federation and the other SAML-P. So organizations that have already a SAML-P-based protocol infrastructure in place, does not need to change in order to be interoperable with an ADFS-based one.