WIF, ADFS 2 and WCF–Part 5: Service Client (more Flexibility with WSTrustChannelFactory)

See the previous posts first.

WIF includes an API to manually request tokens from a token service. This gives you more control over the request and more flexibility since you can use your own token caching scheme instead of being bound to the channel object lifetime.

The API is straightforward. You first request a token from the STS and then use that token to create a channel to the relying party service. I’d recommend using the WS-Trust bindings that ship with WIF to talk to ADFS 2 – they are pre-configured to match the binding configuration of the ADFS 2 endpoints.

The following code requests a token for a WCF service from ADFS 2:

private static SecurityToken GetToken()
{
   
// Windows authentication over transport security
    var factory = new WSTrustChannelFactory
(
       
new WindowsWSTrustBinding(SecurityMode
.Transport),
        stsEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;
 
   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        AppliesTo =
new EndpointAddress
(svcEndpoint),
        KeyType =
KeyTypes
.Symmetric
    };
 
   
var
channel = factory.CreateChannel();
   
return channel.Issue(rst);
}

Afterwards, the returned token can be used to create a channel to the service. Again WIF has some helper methods here that make this very easy:

private static void CallService(SecurityToken token)
{
   
// create binding and turn off sessions
    var binding = new WS2007FederationHttpBinding
(
       
WSFederationHttpSecurityMode
.TransportWithMessageCredential);
    binding.Security.Message.EstablishSecurityContext =
false
;
 
   
// create factory and enable WIF plumbing
    var factory = new ChannelFactory<IService>(binding, new EndpointAddress
(svcEndpoint));
    factory.ConfigureChannelFactory<
IService
>();
 
   
// turn off CardSpace – we already have the token
    factory.Credentials.SupportInteractive = false
;
 
   
var channel = factory.CreateChannelWithIssuedToken<IService
>(token);
 
    channel.GetClaims().ForEach(c =>
       
Console.WriteLine(“{0}n {1}n  {2} ({3})n”
,
            c.ClaimType,
            c.Value,
            c.Issuer,
            c.OriginalIssuer));
}

Why is this approach more flexible? Well – some don’t like the configuration voodoo. That’s a valid reason for using the manual approach. You also get more control over the token request itself since you have full control over the RST message that gets send to the STS.

One common parameter that you may want to set yourself is the appliesTo value. When you use the automatic token support in the WCF federation binding, the appliesTo is always the physical service address. This means in turn that this address will be used as the audience URI value in the SAML token. Well – this in turn means that when you have an application that consists of multiple services, you always have to configure all physical endpoint URLs in ADFS 2 and in the WIF configuration of the service(s).

Having control over the appliesTo allows you to use more symbolic realm names, e.g. the base address or a completely logical name. Since the URL is never de-referenced you have some degree of freedom here.

In the next post we will look at the necessary code to request multiple tokens in a call chain. This is a common scenario when you first have to acquire a token from an identity provider and have to send that on to a federation gateway or Resource STS.

Stay tuned.

This entry was posted in IdentityModel. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s