JSON Web Token
JSON Web Token is an Internet standard for creating data with optional signature and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed either using a private secret or a public/private key. For example, a server could generate a token that has the claim "logged in as admin" and provide that to a client. The client could then use that token to prove that it is logged in as admin. The tokens can be signed by one party's private key so that party can subsequently verify the token is legitimate. If the other party, by some suitable and trustworthy means, is in possession of the corresponding public key, they too are able to verify the token's legitimacy. The tokens are designed to be compact, URL-safe, and usable especially in a web-browser single-sign-on context. JWT claims can typically be used to pass identity of authenticated users between an identity provider and a service provider, or any other type of claims as required by business processes.
JWT relies on other JSON-based standards: JSON Web Signature and JSON Web Encryption.
Structure
Header | Identifies which algorithm is used to generate the signatureHS256 indicates that this token is signed using HMAC-SHA256.Typical cryptographic algorithms used are HMAC with SHA-256 and RSA signature with SHA-256. JWA RFC 7518 introduces many more for both authentication and encryption. | |
Payload | Contains a set of claims. The JWT specification defines seven Registered Claim Names which are the [|standard fields] commonly included in tokens. Custom claims are usually also included, depending on the purpose of the token. This example has the standard Issued At Time claim and a custom claim. | |
Signature | HMAC-SHA256 + '.' + base64urlEncoding | Securely validates the token. The signature is calculated by encoding the header and payload using Base64url Encoding and concatenating the two together with a period separator. That string is then run through the cryptographic algorithm specified in the header, in this case HMAC-SHA256. The Base64url Encoding is similar to base64, but uses different non-alphanumeric characters and omits padding. |
The three parts are encoded separately using Base64url Encoding, and concatenated using periods to produce the JWT:
const token = base64urlEncoding + '.' + base64urlEncoding + '.' + base64urlEncoding
The above data and the secret of "secretkey" creates the token:
This resulting token can be easily passed into HTML and HTTP.
Use
In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned and must be saved locally, instead of the traditional approach of creating a session in the server and returning a cookie.Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the
Authorization
header using the Bearer
schema. The content of the header might look like the following:This is a stateless authentication mechanism as the user state is never saved in server memory. The server's protected routes will check for a valid JWT in the Authorization header, and if it is present, the user will be allowed to access protected resources. As JWTs are self-contained, all the necessary information is there, reducing the need to query the database multiple times.
Standard fields
The internet drafts define the following standard fields that can be used inside a JWT claim set:code | name | description |
iss | Issuer | Identifies principal that issued the JWT. |
sub | Subject | Identifies the subject of the JWT. |
aud | Audience | Identifies the recipients that the JWT is intended for. Each principal intended to process the JWT must identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the aud claim when this claim is present, then the JWT must be rejected. |
exp | Expiration Time | Identifies the expiration time on and after which the JWT must not be accepted for processing. The value must be a NumericDate: either an integer or decimal, representing seconds past 1970-01-01 00:00:00Z. |
nbf | Not Before | Identifies the time on which the JWT will start to be accepted for processing. The value must be a NumericDate. |
iat | Issued at | Identifies the time at which the JWT was issued. The value must be a NumericDate. |
jti | JWT ID | Case sensitive unique identifier of the token even among different issuers. |
The following fields can be used in authentication headers:
Implementations
JWT implementations exist for most languages and frameworks, including but not limited to:- .NET
- C
- Clojure
- Common Lisp
- Dart
- Elixir
- Erlang
- Go
- Haskell
- Java
- JavaScript
- Lua
- Node.js
- OCaml
- Perl
- PHP
- PL/SQL
- PowerShell
- Python
- Raku
- Ruby
- Rust
- Scala
- Swift
Vulnerabilities
Security consultant Tim McLean reported vulnerabilities in some JWT libraries that used the
alg
field to incorrectly validate tokens. While these vulnerabilities were patched, McLean suggested deprecating the alg
field altogether to prevent similar implementation confusion.With proper design, developers can address algorithm vulnerabilities by taking precautions:
- Never let the JWT header alone drive verification
- Know the algorithms
- Use an appropriate key size