Custom token authentication in Azure Functions using bindings

Azure Functions only provides direct support for OAuth
access tokens that have been issued by a small number of providers, such as
Azure Active Directory, Google, Facebook and Twitter. If you want to validate
tokens issued by an external OAuth server or integrate with a custom solution,
you’ll need to create the plumbing yourself.

In the .Net world the ideal mechanism would be to find some way of injecting a ClaimsPrincipal instance into the running function. Validating access tokens based on Json Web Tokens (JWTs) is relatively straightforward, but there’s no middleware in Azure Functions that you inject the result.

You could add some boiler plate at the beginning of every
function, but this is a little messy and difficult to test. Ideally you need to
separate function definitions from the authentication mechanism they are using,
so they can just consume a ClaimsPrincipal that has been created elsewhere.

This can be done by creating a custom input binding that can be used to make the ClaimsPrincipal part of the function definition. The method signature below shows what this looks like – the principal argument has been decorated with a custom binding argument called AccessToken:

This approach eliminates the need for boiler plate and makes
the validation of access tokens an external concern. It also makes the function
more testable as you can inject security principals into the function from test
code.

The full code for this example is posted in GitHub, but the idea was taken from Boris Wilhem’s on-going work around implementing dependency injection in Azure Functions. He uses a similar approach to allow you to define dependencies in start-up code that are injected into methods at run-time.

Creating the custom input binding

The implementation involves creating half a dozen small
classes to wire everything into the Functions SDK:

An attribute that is used to annotate the
ClaimsPrincipal argument in the function definition

A custom binding made up of three classes that
reads the access token in the incoming request and creates a ClaimsPrincipal to
be returned to the function

An extension configuration provider that wires
the attribute and the custom binding together.

An extension method that lets you register the binding
when the Azure Function host starts up.

The attribute definition can be a simple, empty attribute class definition that is decorated with a Binding attribute.

Custom bindings can be straightforward, though this
implementation is complicated by the need to access the underlying HTTP request
for the access token. This requires three classes:

A custom binding
provider that implements IBindingProvider – this will be associated
directly to the attribute definition.

The provider will be expected to return a binding that implements IBinding. The
binding class is where you have access to the underlying request context so can
obtain application settings and the HTTP request header.

The binding will be responsible for returning a value provider that implements
IValueProvider. This is where you do the work to crack open the JWT and create
the ClaimsPrinciple.

To wire attribute and binding together an extension configuration provider is required that implements IExtensionConfigProvider. All this class does is define a rule for the attribute definition that will be picked up by the Azure Functions runtime. This rule can associate the attribute with a custom binding as shown below:

Finally, you’ll need to tell the Azure Functions host about the binding when it starts up. Firstly, you create an extension method that lets you add the binding to the host’s IWebJobsBuilder context as shown below:

This code is executed in a custom Startup method that you’ll need to add to your project. The code below demonstrates this – note the use of the assembly attribute that tells the Azure Functions runtime to use the Startup class when the host initializes.

Validating the token

All the work around token validation happens in the value provider
class – AccessTokenValueProvider. This should receive all the configuration and context information it needs from the binding class, allowing for a clean and testable implementation that generates a ClaimsPrincipal from the incoming token.

The token will be decrypted using the key specified in the IssuerSigningKey property.

It will also validate the token’s issuer and intended audience against the values in the ValidIssuer and ValidAudience properties

The token’s lifetime will be checked to ensure that it hasn’t expired.

Assuming that the token is being supplied as a “bearer token”, you’ll need to take it from the “Authorization” header and strip off the leading “Bearer ” text. The actual token validation only requires a few lines of code:

A caveat – returning an appropriate HTTP status

Note that this implementation is incomplete in one important respect. Any validation failures will throw an exception to the Azure Functions run-time and a 500 Internal Server Error status code will be returned to the user with no message. There is no way of interrupting this response and returning something more useful to the client, e.g. a 403 Forbidden response.

To do this you’ll need to wrap the principal into along with a status and any exceptions that occurred while validating the token. This wrapped result should be returned to the Azure function which will then be responsible for interpreting the result and returning the appropriate HTTP response.

About me

I am a London-based technical architect who has spent more than twenty years leading development across start-ups, digital agencies, software houses and corporates.
Over the years I have built a lot of stuff including web sites and services, multi-screen applications, systems integrations and middleware.

My current focus is on enabling scalable SaaS delivery and providing architectural leadership in agile environments.
I currently work as Chief Architect for Wolters Kluwer UK leading them to cloud heaven, one service at a time. Opinions are my own and not the views of my employer, etc.

Recent

There does seem to be growing confusion over what Service Fabric is really for. Is it an orchestrator for microservices? A means of lifting and shifting legacy applications into the cloud? An application development framework?

Azure Functions only provides direct support for a narrow range of authentication providers. If you want to use an external token provider or custom solution, you’ll have to create the plumbing yourself.

ArchUnit is a java library that provides a fluent API for creating self-testing architectures via unit tests. A similar library can be written for .Net Standard that acts on compiled assemblies rather than raw code.

There is a growing sense of unease around how larger organisations have implemented agile. In particular, there is a tendency towards centralised control that can be at odds with the agile preference for individuals over process.