tl;dr: if you understand why and how to support blacklisting JWTs, then skip to the code.

On a previous post we proposed an approach to using JSON Web Tokens as API Keys, going over some of the benefits of doing so and also providing some examples based on our API v2 scenarios. This post follows up by explaining an aspect that was not covered before: how to blacklist a JWT API key so it is no longer valid.

A real world example

Let's for a second assume that GitHub used JSON Web Tokens as API Keys and one of them was accidentally published on the web. You would want to make sure an app can no longer access your information by revoking that token:

Framing the problem

Providing support for blacklisting JWTs poses the following questions:

How are JWTs individually identified?

Who should be able to revoke JWTs?

How are tokens revoked?

How do we avoid adding overhead?

This blog post aims to answer the previous questions by leveraging our experience from implementing this feature in our API v2.

1. How are JWTs individually identified?

To revoke a JWT we need to be able to tell one token apart from another one. The JWT spec proposes the jti (JWT ID) as a means to identify a token. From the specification:

The jti (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well.

As a quick reminder, this is how the claims section of one of our JWT API tokens looks like:

The tokens accepted by our API use the aud claim to determine the tenant for which the JWT is valid. If we use the (aud, jti) pair as the token's identifier then each tenant is in charge of guaranteeing that there's no duplication among their tokens.

Similarly, if a token does not include the jti claim we do not allow it to be revoked.

2. Who should be able to revoke JWTs?

If anyone could revoke our API keys then unfortunately they wouldn't be of much use. We need a way of restricting who can revoke a JWT.

The way we solved it in our API is by defining a specific scope (permission) that allows blacklisting tokens. If you generate a JWT like the one shown in the next figure you will be able to revoke JWTs:

Notice the blacklist action nested inside the scopes object.

3. How are tokens revoked?

To blacklist/revoke a token, you need a JWT API key (referred to as JWT_API_KEY) like the one described in #2. With it you can issue a POST request to /api/v2/blacklists/tokens as shown below (new lines added for clarity):