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?
- JWTs can be added to the URL, sent via POST as part of a parameter, or included in the HTTP request header.
- It contains a payload with information about the sender, issued date, expiration date, etc.
- 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.
- 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.
- 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
Authorization
field using theBearer
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()
andsetIssuer(String)
- Subject (sub):
getSubject()
andsetSubject(String)
- Audience (aud):
getAudience()
andsetAudience(String)
- Expiration (exp):
getExpiration()
andsetExpiration(Date)
- Not Before (nbf):
getNotBefore()
andsetNotBefore(Date)
- Issued At (iat):
getIssuedAt()
andsetIssuedAt(Date)
- JWT ID (jti):
getId()
andsetId(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.