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

Posted by Your DisplayName here! on Least Privilege See other posts from Least Privilege or by Your DisplayName here!
Published on Thu, 14 Oct 2010 15:47:04 GMT Indexed on 2010/12/06 17:00 UTC
Read the original article Hit count: 357

Filed under:

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.

© Least Privilege or respective owner

Related posts about IdentityModel