Consuming PoP tokens in a Katana pipeline

Consuming PoP tokens in a web api is a two-part configuration. The first part is configuring your token validation middleware normally, except with some slight modifications to accommodate how PoP tokens are passed. The second part is configuring middleware to confirm the proof of possession key by validating the signature in the PoP token against the current HTTP request.

The IdentityModel.Owin.PopAuthentication NuGet package provides the necessary code to accomplish this configuration.

Changes to the normal token validation middleware

The two main changes that need to be done to accommodate PoP tokens is to change the middleware’s authentication scheme to "PoP" and to configure a token provider to locate the access token within the PoP token.

It is simple to configure the authentication middleware to use the "PoP" scheme – just set the AuthenticationType property to "PoP" (notice both instances of the letter P must be uppercase).

To configure a token provider to locate the access token within the PoP token, you will need to set the Provider property and handle the OnRequestToken event. There is a helper method DefaultPopTokenProvider.GetAccessTokenFromPopTokenAsync that can perform this work for you.

If you are using the IdentityServer3.AccessTokenValidation middleware, then the configuration changes will look like this:

public void Configuration(IAppBuilder app)
{
    JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();

    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
    {
        // The HttpSignatureValidation middleware looks for another middleware called PoP
        AuthenticationType = "PoP",
        
        // locate the access token from within  the PoP token
        Provider = new OAuthBearerAuthenticationProvider
        {
            OnRequestToken = async ctx =>
            {
                ctx.Token = await DefaultPopTokenProvider.GetAccessTokenFromPopTokenAsync(ctx.OwinContext.Environment);
            }
        },
        
        // ...
    };
}

If you are using the Microsoft.Owin.Security.Jwt middleware, then the configuration will look like this:

public void Configuration(IAppBuilder app)
{
    JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();

    app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
    {
        // The HttpSignatureValidation middleware looks for another middleware called PoP
        AuthenticationType = "PoP",
        
        // locate the access token from within  the PoP token
        Provider = new OAuthBearerAuthenticationProvider
        {
            OnRequestToken = async ctx =>
            {
                ctx.Token = await DefaultPopTokenProvider.GetAccessTokenFromPopTokenAsync(ctx.OwinContext.Environment);
            }
        },  
              
        // ...
    };
}

Middleware to validate HTTP request against proof of possession key

Once the above code is able to locate and validate the access token from within the PoP token, the signature in the PoP token must be validated against the current HTTP request. To perform this validation, simply register the HttpSignatureValidationMiddleware in the Katana pipeline after the access token validation middleware.

It will look like this:

public void Configuration(IAppBuilder app)
{
    JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();

    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
    {
        // The HttpSignatureValidation middleware looks for another middleware called PoP
        AuthenticationType = "PoP",
        
        // locate the access token from within  the PoP token
        Provider = new OAuthBearerAuthenticationProvider
        {
            OnRequestToken = async ctx =>
            {
                ctx.Token = await DefaultPopTokenProvider.GetAccessTokenFromPopTokenAsync(ctx.OwinContext.Environment);
            }
        },
        
        // ...
    };
    
    app.UseHttpSignatureValidation();
}

The default signature validation will use the incoming access token and the timestamp contained in the PoP token. If you require signature validation on other aspects of the HTTP request, then a HttpSignatureValidationOptions can be passed to the UseHttpSignatureValidation API.

The HttpSignatureValidationOptions contains these properties for configuring the request validation:

A sample can be found here.