January 7th, 2021

WSFederationHttpBinding in .NET Standard

Mike Rousos
Principal Software Engineer

As .NET Core has evolved, the WCF team has worked to expand support for WCF client scenarios on .NET Standard and .NET Core. Until recently, one of the gaps developers faced when building WCF clients for .NET Core was the lack of WSFederationHttpBinding and WS2007FederationHttpBinding. These bindings support WS-Federation authentication scenarios where users authenticate with a security token service (like Active Directory Federation Services) and use a token from that authentication provider to authenticate with a separate service (called the ‘relying party’). Last month, the System.ServiceModel.Federation package (targeting .NET Standard 2.0) released, enabling these client WCF scenarios!

This post covers the basics of getting started with System.ServiceModel.Federation in your .NET Core application. It goes over how to install the package and how its use differs from previous WS-Fed WCF scenarios.

Using WSFederationHttpBinding

To use the .NET Standard-compatible version of WSFederationHttpBinding, add a reference to the System.ServiceModel.Federation package with version 4.8.0.

<PackageReference Include="System.ServiceModel.Federation" Version="4.8.0" />

This package contains the WSFederationHttpBinding type that is now used for both WSFederationHttp and WS2007FederationHttp scenarios. A key difference between .NET Framework WCF scenarios and .NET Core WCF scenarios is that .NET Core doesn’t use application config files for setting up WCF objects, so the binding will need to be configured in code rather than in app.config, as you might have previously done for .NET Framework.

If you’re using a WCF client (derived from ClientBase<T>) to interact with your WCF service, you can use the client’s constructor that takes a Binding and an EndpointAddress as parameters. In many cases, existing client code generated by .NET Framework’s SvcUtil will continue to work. Just make sure you’re using client constructors that accept a binding as a parameter instead of one that expects to create the binding from configuration. Updates to dotnet-svcutil and Visual Studio’s WCF Web Service Reference Provider Tool are planned which will enable auto-generating .NET Standard-specific clients for WCF services with WS-Federation bindings.

The WSFederationHttpBinding constructor takes a single parameter of type WSTrustTokenParameters. This parameter is used to specify details about the token issuer (STS) the binding should get tokens from and how those tokens should be handled. The easiest way to create an instance of WSTrustTokenParameters is to use the WSTrustTokenParameters.CreateWS2007FederationTokenParameters or WSTrustTokenParameters.CreateWSFederationTokenParameters helper methods. These static methods will create WSTrustTokenParameters for WS2007Federation and WSFederation scenarios, respectively. Both methods take the issuer binding (also called the ‘inner binding’) and endpoint address as parameters. It’s also possible to create your own WSTrustTokenParameters via the constructor and specify exactly the behavior you need. Important properties on the WSTrustTokenParameters type include:

  • IssuerAddress This is an EndpointAddress for the STS that the federation binding should get tokens from.
  • IssuerBinding This property represents what is sometimes known as the inner binding – the WCF binding used for communicating with the token issuer. This is often a WSHttpBinding or WS2007HttpBinding, but will vary based on the scenario and should match the type of binding that would have been used for the issuerBinding in a .NET Framework app.config file.
  • MessageSecurityVersion This property specifies which versions of WSSecurity, WSTrust, WSSecureConversation, and WSSecurityPolicy should be used. If you were previously using WSFederationHttpBinding, then the correct value for this property is WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10. If you were previously using WS2007FederationHttpBinding, then the correct value is WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10. Using the CreateWSFederationTokenParameters or CreateWS2007FederationTokenParameters helper methods will initialize this properly automatically.
  • TokenType This optional property specifies the type of token that should be requested from the issuer.
  • CacheIssuedTokens, MaxIssuedCachingTime, and IssuedTokenRenewalThresholdPercentage These properties indicate whether tokens should be cached and for how long. In many cases, these properties don’t need to be set as the defaults (tokens are cached for 60% of their lifetime) are sufficient.
  • EstablishSecurityContext This boolean determines whether or not to use a secure conversation context. Again, this property often doesn’t need to be set because the default (true) is common.
  • RequestContext An optional string that will be passed along in WS-Trust requests to the token issuer that can help with correlating messages for diagnostic purposes.

Once the WSTrustTokenParameters instance has been created and passed to a WSFederationHttpBinding, that binding can be used to create a WCF client (derived from ClientBase) or ChannelFactory.

Here is an example of creating a typical WSFederationHttpBinding:

// First, create the inner binding for communicating with the token issuer.
// The security settings will be specific to the STS and should mirror what
// would have been in an app.config in a .NET Framework scenario.
var issuerBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);
issuerBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
issuerBinding.Security.Message.EstablishSecurityContext = false;

// Next, create the token issuer's endpoint address
var endpointAddress = new EndpointAddress("https://<IssuerAddress>/adfs/services/trust/13/usernamemixed");

// Finally, create the WSTrustTokenParameters
var tokenParameters = WSTrustTokenParameters.CreateWS2007FederationTokenParameters(issuerBinding, endpointAddress);

// This workaround is necessary only until an updated System.ServiceModel.Federation ships with
// https://github.com/dotnet/wcf/issues/4426 fixed.
// The CreateWSFederationTokenParameters helper method does not have this bug.
tokenParameters.KeyType = SecurityKeyType.SymmetricKey;

// Create the WSFederationHttpBinding
var binding = new WSFederationHttpBinding(tokenParameters);

A sample client using WSFederationHttpBinding is available on GitHub.

Wrap up

With the release of System.ServiceModel.Federation, it is now be possible to implement scenarios that consume WCF services with WS-Federation bindings on .NET Core. The System.ServiceModel.Federation package is built from the WCF repository, so please leave feedback there if you run into anything that doesn’t work right.

Author

Mike Rousos
Principal Software Engineer

Mike's a long-time member of the .NET team. He lives in northeast Ohio with his wife and four kids.

4 comments

Discussion is closed. Login to edit/delete existing comments.

  • Jozef Raschmann

    Have tried but seems derived keys are not supported (WSTrustTokenParameters.RequireDerivedKeys). The WSFederationHttpBinding automatically sets it to false.

  • silkfire

    Never thought I’d see such an incommodious property name as

    WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10

    in an official Microsoft package 🙂

    • Mike RousosMicrosoft employee Author

      Yea, that name is definitely a mouthful. 🙂 It’s long because it’s trying to capture all the different components of a message security version. There are probably other (more succinct) ways of doing that, but those properties have been around for a while now (since 3.0, I think), so we don’t want to change them now.

    • Stuart Lang

      and on the previous line

      WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10

      😆🙈