Shared Authentication with JSON Web Tokens

Published

I have been working on a side project that features three separate REST APIs, all hosted on different servers. I needed to find a way to authenticate between them, and the idea of a shared session store sounded like a hassle. My research eventually led me to JSON Web Tokens, which I found out are a great way to handle authentication in distributed environments, and involve relatively little set up compared to something like oAuth.

Traditional Authentication Systems

As a self-taught developer I was very familiar with key-based authentication: supply the username and password in a POST request, which triggers a database lookup on the backend. If the credentials are valid, the server response sets a Cookie with a Session ID. The Session ID cookie is supplied with all subsequent requests, and is validated on each request to make sure the user’s session is still valid.

Key-based Authentication: a Session ID is obtained and validated on all requests

Things get a little more interesting with token-based authentication. While the behavior to obtain a token is similar (supply login credentials to server, receive token back), tokens can include more information than just a Session ID. In fact, tokens can contain information about user or session itself, and save backend servers from having to perform database look-ups for each request.

JSON Web Tokens, a web industry standard, allow for a customizable token payload and establish a standard authentication scheme that can lead to performance benefits over traditional approaches, and can be used fairly easily in distributed systems1.

JSON Web Tokens

Just like other token-based authentication schemes, JSON Web Tokens (JWT) are obtained from an authentication server after a user supplies login credentials. The JSON Web Token standard dictates how a token should be structured so that it can include a payload (e.g. user or session information), while still being secure enough to authenticate users.

Contents of a JSON Web Token, adapted from source

Each section of the JWT is base64 encoded. The header specifies the hashing algorithm used to sign the token, and the payload contains any pertinent user information, which can change based on the needs of the system. The header and payload are then hashed to generate a signature. This signature is what ensures the contents of the JWT (i.e. Payload) were not tampered with during transmission.

When a web service is trying to validate a JWT and determine if a user should be granted access, a pre-shared key (or public key, if an asymmetric hashing algorithm was used) is used to hash the header and payload of the JWT together. If this hash matches the JWT’s signature, the token is valid and the user is granted access. If the payload has been altered, the hash created during validation will not match the signature, and the token will be invalid.

Shared Authentication between multiple Web Services

The main benefit of JWTs over traditional key-based authentication is that requests can be validated locally at the endpoint with a simple hash comparison, a break from the traditional database lookup used to verify that a Session ID is still valid.

JWT Authentication: distributed endpoints validate tokens locally

This means that when trying to secure multiple web services in a distributed environment, each web service only needs the pre-shared key (or public key if an asymmetric hashing algorithm was used) to validate JWTs. No communication with the authentication server is required, which is much more performant and can be easier to configure.

Public/Private keys and Asymmetric Hashing

The beauty of JSON Web Tokens is their flexibility – there are many different hashing algorithms that can be used to sign and verify JWTs. This includes simple algorithms that hash based on a pre-shared key, as well as asymmetric algorithms that use public/private key cryptography.

One commonly supported asymmetric algorithm is RS-256. Under this scheme, the authentication server uses it’s  private key to sign the JWT upon creation. Other web services then use the public key to verify JWT signatures and authenticate requests. This is huge because it eliminates the task of securely managing private keys between different web servers.

Wrap Up

In summary, JSON Web Tokens can improve performance by removing the need to communicate with an authentication server or database when verifying requests. They also work great in a distributed environments, and only require that a pre-shared key (or public key if using an asymmetric hashing algorithm) be shared ahead of time.

JSON Web Tokens are also incredibly flexible – their payload can contain whatever information is required by the system. There are several open source libraries available which make using JWTs easy in a variety of languages.  While JWTs can be used with something like oAuth, it is not required2, and it is generally much easier to configure a standalone JWT scheme.

In my research, the only drawback I found for JWTs is that since they are a stateless authentication mechanism3, administrators cannot revoke a token – a JWT will remain valid until it expires.

References

  1. JWT Tokens for distributed authentication
  2. Stack Overflow: What is the difference between OAuth based and Token based authentication?
  3. The Purpose of JWT: Stateless Authentication