JWTs with Spring Boot
- Secure: JWTs are signed by using a secret or a public/private key pair.
- Self-contained: all information is stored inside the JWT token. No need for further database calls.
- Unmodifiable information, but exposed: Do not put secrets inside JWTs.
- Compact format: JWTs are lightweight.
How Does It Work?
- JWTs can be added to the URL, sent via POST as part of a parameter or added to the HTTP request header.
- It contains a payload with information about the sender, issued date, expiration date…
- JWTs are usually generated during the authentication phase, and once the user is logged in, the JWT previously generated allows the user to access to resources without having to make additional calls to databases.
- They can be used to exchange information between services in a secure way, making sure that it was not modified during the transmission. This is possible because the signature is calculated using the header and payload.
- The token is stored locally or in a cookie.
- When the user wants to use the token, the convention is to add it to the header in the
Authorizationfield using the
Bearerprefix followed with the token value.
JWTs are structured in three parts separated by dots:
- Header: contains the token type (jwt) and hashing algorithm like SHA256 or RSA.
- Payload: contains claims, which is the metadata (subjects, senders, or expiration date). There are three kinds of claims: registered, public, and private.
- Signature: the combination of header, payload, secret, and the algorithm specified in the header. The signature ensures that nothing has changed.
As a result, the format is
jjwt library provides all you need to generate signed tokens in a Java application.
<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):
- Subject (sub):
- Audience (aud):
- Expiration (exp):
- Not Before (nbf):
- Issued At (iat):
- JWT ID (jti):
All these parameters are available through Claims getters.
Verify JWT Token:
final Claims claims = Jwts.parser() .setSigningKey(JWT_SECRET) .parseClaimsJws(compactJws) .getBody();
JWT_SECRETis the secret used when we generate the token.
compactJwsis the JWT token pass in the header.
If the verfication succeed 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
SignatureException is thrown.
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.