JWTs with Spring Boot


24 Apr 2018  Sergio Martin Rubio  3 mins read.

JWT (JSON Web Token) is an open-source standard commonly used to transmit data between two services in a compact and secure way. This standard offers a wide range of libraries to generate JWTs, including libraries for platforms such as .NET, Python, Node.js, Java, JavaScript, Perl, Ruby, Elixir, Golang, Groovy, and Haskell.

Features

  • Secure: JWTs are signed using either a secret or a public/private key pair.
  • Self-contained: All information is stored inside the JWT token, eliminating the need for further database calls.
  • Unmodifiable information, but exposed: Avoid putting secrets inside JWTs.
  • Compact format: JWTs are lightweight.

How Does It Work?

JWT Communication
JWT Communication
  1. JWTs can be added to the URL, sent via POST as part of a parameter, or included in the HTTP request header.
  2. It contains a payload with information about the sender, issued date, expiration date, etc.
  3. JWTs are usually generated during the authentication phase. Once the user is logged in, the previously generated JWT allows access to resources without additional calls to databases.
  4. They can be used to exchange information between services securely, ensuring that it was not modified during transmission. This is possible because the signature is calculated using the header and payload.
  5. The token is stored locally or in a cookie.
  6. When the user wants to use the token, the convention is to add it to the header in the Authorization field using the Bearer prefix followed by the token value.

For example:

Authorization: Bearer <token>

JWT format

JWTs are structured in three parts separated by dots:

  • Header: Contains the token type (jwt) and the hashing algorithm like SHA256 or RSA.
  • Payload: Contains claims, which are metadata (subjects, senders, expiration date). There are three kinds of claims: registered, public, and private.
  • Signature: The combination of the header, payload, secret, and the algorithm specified in the header. The signature ensures that nothing has changed.

As a result, the format is xxx.yyy.zzz

Java Integration

The jjwt library provides all you need to generate signed tokens in a Java application.

Maven dependency:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

Generate JWT Token:

String jwt = Jwts.builder()
    .setClaims(claims)
    .setSubject(email)
    .setIssuedAt(new Date())
    .setExpiration(new Date(System.currentTimeMillis()+ JWT_EXPIRATION_TIME))
    .signWith(SignatureAlgorithm.HS256, JWT_SECRET)
    .compact();
  • Issuer (iss): getIssuer() and setIssuer(String)
  • Subject (sub): getSubject() and setSubject(String)
  • Audience (aud): getAudience() and setAudience(String)
  • Expiration (exp): getExpiration() and setExpiration(Date)
  • Not Before (nbf): getNotBefore() and setNotBefore(Date)
  • Issued At (iat): getIssuedAt() and setIssuedAt(Date)
  • JWT ID (jti): getId() and setId(String)

All these parameters are available through Claims getters.

Verify JWT Token:

final Claims claims = Jwts.parser()
    .setSigningKey(JWT_SECRET)
    .parseClaimsJws(compactJws)
    .getBody();
  • JWT_SECRET is the secret used when we generate the token.
  • compactJws is the JWT token passed in the header.

If the verification succeeds, we will be able to store the metadata in a claims variable that is available to consume later. On the other hand, if the verification fails, a SignatureException is thrown.

Troubleshooting

In case you are using Java 9+, make sure you add an explicit dependency to the POM file.

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
</dependency>

jaxb-api is missing in Java 9, and until jjwt adds the dependency or removes the usage of JAXB classes, we have to add it manually.

Source Code