WIF, ADFS 2 and WCF–Part 6: Chaining multiple Token Services

Posted by Your DisplayName here! on Least Privilege See other posts from Least Privilege or by Your DisplayName here!
Published on Thu, 28 Oct 2010 10:03:58 GMT Indexed on 2010/12/06 17:00 UTC
Read the original article Hit count: 382

Filed under:

See the previous posts first.

So far we looked at the (simpler) scenario where a client acquires a token from an identity provider and uses that for authentication against a relying party WCF service.

Another common scenario is, that the client first requests a token from an identity provider, and then uses this token to request a new token from a Resource STS or a partner’s federation gateway.

This sounds complicated, but is actually very easy to achieve using WIF’s WS-Trust client support. The sequence is like this:

  1. Request a token from an identity provider. You use some “bootstrap” credential for that like Windows integrated, UserName or a client certificate. The realm used for this request is the identifier of the Resource STS/federation gateway.
  2. Use the resulting token to request a new token from the Resource STS/federation gateway. The realm for this request would be the ultimate service you want to talk to.
  3. Use this resulting token to authenticate against the ultimate service.

Step 1 is very much the same as the code I have shown in the last post. In the following snippet, I use a client certificate to get a token from my STS:

private static SecurityToken GetIdPToken()
{
   
var factory = new WSTrustChannelFactory
(
       
new CertificateWSTrustBinding(SecurityMode
.TransportWithMessageCredential,
        idpEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;
 
    factory.Credentials.ClientCertificate.SetCertificate(
       
StoreLocation
.CurrentUser,
       
StoreName
.My,
       
X509FindType
.FindBySubjectDistinguishedName,
       
"CN=Client"
);
 
   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        AppliesTo =
new EndpointAddress
(rstsRealm),
        KeyType =
KeyTypes
.Symmetric
    };
 
   
var
channel = factory.CreateChannel();
   
return channel.Issue(rst);
}

To use a token to request another token is slightly different. First the IssuedTokenWSTrustBinding is used and second the channel factory extension methods are used to send the identity provider token to the Resource STS:

private static SecurityToken GetRSTSToken(SecurityToken idpToken)
{
   
var binding = new IssuedTokenWSTrustBinding
();
    binding.SecurityMode =
SecurityMode
.TransportWithMessageCredential;
 
   
var factory = new WSTrustChannelFactory
(
        binding,
        rstsEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;
    factory.Credentials.SupportInteractive =
false
;
 
   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        AppliesTo =
new EndpointAddress
(svcRealm),
        KeyType =
KeyTypes
.Symmetric
    };
 
    factory.ConfigureChannelFactory();
   
var
channel = factory.CreateChannelWithIssuedToken(idpToken);
   
return
channel.Issue(rst);
}

For this particular case I chose an ADFS endpoint for issued token authentication (see part 1 for more background). Calling the service now works exactly like I described in my last post.

You may now wonder if the same thing can be also achieved using configuration only – absolutely. But there are some gotchas. First of all the configuration files becomes quite complex. As we discussed in part 4, the bindings must be nested for WCF to unwind the token call-stack. But in this case svcutil cannot resolve the first hop since it cannot use metadata to inspect the identity provider. This binding must be supplied manually.

The other issue is around the value for the realm/appliesTo when requesting a token for the R-STS. Using the manual approach you have full control over that parameter and you can simply use the R-STS issuer URI. Using the configuration approach, the exact address of the R-STS endpoint will be used. This means that you may have to register multiple R-STS endpoints in the identity provider. Another issue you will run into is, that ADFS does only accepts its configured issuer URI as a known realm by default. You’d have to manually add more audience URIs for the specific endpoints using the ADFS Powershell commandlets.

I prefer the “manual” approach.

That’s it. Hope this is useful information.

© Least Privilege or respective owner