WCF: Validating a bearer token using a DispatchMessageInspector

WCF: Validating a bearer token using a DispatchMessageInspector

30 September 2014

Unfortunately, I can't use Katana for everything and have to work with older systems. In my case I was working with a Spring (IoC) configured ServiceHost.

During my OpenId Connect work I needed my WCF Relying Party to inspect a bearer Access Token in JWT format.
I wanted to decorate my interface with a custom attribute detailing which scopes have access before invoking the implementing code.

Example, my interface with AllowedScopes attribute:

[ServiceContract]
public interface IHelloWorldService
{
    [WebGet(UriTemplate = "/hello", BodyStyle = WebMessageBodyStyle.Bare)]
    [OperationContract]
    [AllowedScopes("read")]
    Stream GetHello();
}

To ease my tests development I used a shared symmetric key for signing the JWT. In my real world scenario; I will use an asymmetric key where the public key is accessible and can be used to verify the signature.

A JSON Web Token (JWT)

JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).

See jwt.io where I got a sample JWT.

Encoded

eyJpc3MiOiJodHRwOi8vY2h3aWxsaWFtc29uLm1lLnVrIiwiYXVkIjoiaHR0cDovL2
Nod2lsbGlhbXNvbi5tZS51ay9hdWRpZW5jZSIsIm5iZiI6MTQxMjA3MTY5NywiZXhw
IjoxNDEyMTU4MDk3LCJzY29wZSI6InJlYWQifQ

Decoded

{
  "iss": "http://chwilliamson.me.uk",
  "aud": "http://chwilliamson.me.uk/audience",
  "nbf": 1412071697,
  "exp": 1412158097,
  "scope": "read"
}

A custom DispatchMessageInspector

I created my own implementation of the IDispatchMessageInspector called AuthorizationDispatchMessageInspector to read to the Authorization bearer token header. The inspector is added to the Dispatcher runtime using an implementation of IEndpointBehavior called AuthorizationBehavior.

ServiceHost stanza: adding the AuthorizationBehavior to the HelloWorldService endpoint.

public void OpenSimpleHelloWorldServiceWithAuthorization() {
    // .....service host creation

    // the first will be for hello world.
    var endpoint = serviceHost.Description.Endpoints.First();

    // adds our behavior.
    endpoint.Behaviors.Add(new AuthorizationBehavior());
    return disposableHost.Start();
}

AuthorizationBehavior stanza; adding the AuthorizationDispatchMessageInspector to the dispatcher runtime.

public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new AuthorizationDispatchMessageInspector());
}

My unhappiness

Unfortunetly, I am unhappy with the way I am discovering the Contract. I seem to have muddled my way through here.

var serviceType = instanceContext.Host.Description.ServiceType.GetInterfaces()[0];
var operationName = OperationContext.Current.IncomingMessageProperties["HttpOperationName"] as string;

Hopefully, in time someone will modify and correct my example.

Git project

See my research is at WCF.Research.

.NET AuthN AuthZ CSharp oAuth OpenId-Connect-1.0 WCF