Azure Functions with JWT Authentication

If you’re building Azure Functions, you generally have two options when it comes to implementing authentication and authorization:

  1. Use the App Service Authentication integration which is great if you are using one of the standard identity providers (Azure AD, Microsoft Account, Facebook, Google, and Twitter).
  2. Use custom authentication.  The Microsoft documentation discusses this in the context of a standard MVC app and leaves some gaps.

Let’s take a look at how we can implement custom authentication for Azure Functions using JWT.

(I’ve pushed a fully functioning example here so you have a quick start to work from: to get your own authentication scenario working)

Setting Up Our Project

It’s important to note that when you use custom authentication with Functions, you want to set up your application with anonymous authentication as we will be handling authentication checks at the function level.

Performing the Credential Check

The first step is to perform the credential check.  This simply means we check to see if some set of credentials we’ve received matches a set of credentials stored in a custom database or some other service/protocol other than the standard ones provided by App Services.  In this example, we are going to pass a JSON object as the argument to our function and simply return true each time.

Here is our simple stub in Functions:

In the real world, you would implement your custom logic for checking whether the user’s authentication credentials were valid or not.  You can use any mechanism you like such as an existing database, WebAuthn, an Excel spreadsheet (hey, if that’s what floats your boat!)

We can test this service in Postman:

Issuing the JWT

JSON Web Tokens are simply a mechanism for securely transferring JSON strings.  Rather than having the user pass credentials back and forth on each call and then checking the user’s credentials over and over, we can simply retrieve the relevant information about the user and encrypt it into a token which we return to the client as a cookie.  When the client makes subsequent calls, the client passes the JWT back which the application will decrypt and verify that the contents are valid.

Note that because the token is passed with each request, you’ll want to be cautious not to go overboard and only add key data like the username, user ID, user email, role(s) and so on.

We’re going to use the JWT package to generate and parse our tokens:

Now when we call the function, we get back a JWT token which is encrypted with our key (which is just an arbitrary string; pick a long, random one!):

In the application, you’ll want to hold onto this and then return it with each request.

For example, in Axios, we can do something like this:

This ensures that each subsequent function invocation through Axios will automatically have the authorization token included as a header.

Consuming the JWT

Now that we have the token, let’s see how we can consume it.

We’re going to write a simple wrapper class which encapsulates the decoding portion of the JWT flow:

And here’s how we use it from a hypothetical function that updates a user password:

We need the request this time as it is necessary for reading the header.

When we make the request from Postman, we need to add the Authorization header manually by copying the result from the authorization call:

And we set the body to “5678”.

That’s all there is to it!

Next Steps

There are a few challenges with this approach.  Namely, it means that you need to remember to perform an authorization check with each function invocation.  It is possible to use IFunctionInvocationFilter  to build a generic base class that checks authorization for each call and then makes the claims available on the base class.  This simplifies implementation of authenticated and authorized services.

Now we can simply inherit from this class and all of our functions within our new class will be authorized!

Grab the source code here:

If you liked this article, you might also be interested in Azure Functions with CosmosDB and GraphQL.

You may also like...

3 Responses

  1. May 24, 2020

    […] Check out my followup article on how to perform custom authentication and authorization in Functions… […]

  2. September 21, 2020

    […] For service level authentication and authorization, check out my other article on Azure Functions and JWT. […]

  3. February 16, 2021

    […] I’ve encountered my fair share of gaps in the Azure documentation (one of the reasons I wrote this post on Functions with JWT authentication), but I know that the AWS documentation — at least as it pertains to Amplify and AppSync […]

%d bloggers like this: