In modern web development, securing APIs is crucial. One of the most popular standards for authentication is the JSON Web Token (JWT).
In this tutorial, we will learn how to generate a secure JWT using Spring Boot. Unlike standard tutorials that often use email addresses, we will build a system that authenticates using a Phone Number and includes custom Roles inside the token.
We will build a simple REST API endpoint. When a user sends their phone number and roles, our application will sign this data using a secret key and return a JWT string. This token can later be used by the client to access protected resources.
Step 1: Project Setup and Dependencies
Step 2: Configure Application Properties
Step 3: Create the Request DTO
Step 4: Create the JWT Service
Step 5: Create the Controller
Step 6: How to Test This?1. 1. Step 1: Project Setup and Dependencies
First, create a new Spring Boot project. If you are using Spring Initializr, select "Spring Web".
Once created, open your pom.xml file. We need to add the Auth0 Java JWT library to handle the token generation.
1. pom.xml
xxxxxxxxxx<dependencies> <!-- Spring Web Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Auth0 JWT Library --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>4.4.0</version> </dependency> <!-- Lombok (Optional, for less boilerplate code) --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency></dependencies>2. Step 2: Configure Application Properties
We need to define a Secret Key (used to sign the token so it cannot be tampered with) and an Expiration Time (how long the token is valid).
1. File: src/main/resources/application.properties
spring.application.name=PlanetLearningJWT# A strong secret key for signing the token (Keep this safe in production!)jwt.secret=MySecretPlanetLearningKey123!# Token expiration time in milliseconds (e.g., 1 hour = 3600000)jwt.expiration=36000003. Step 3: Create the Request DTO
We need a simple Java class to represent the data coming from the user (the phone number and their roles). This is often called a DTO (Data Transfer Object).
1. File: src/main/java/com/planetlearning/jwt/dto/TokenRequest.java
xxxxxxxxxxpackage com.planetlearning.jwt.dto;import java.util.List;public class TokenRequest { private String phoneNumber; private List<String> roles; // Getters and Setters public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } public List<String> getRoles() { return roles; } public void setRoles(List<String> roles) { this.roles = roles; }}4. Step 4: Create the JWT Service
This is the core logic of the tutorial. We will create a service that takes the phone number and roles, sets the expiration time, and signs the token using the algorithm.
1. File: src/main/java/com/planetlearning/jwt/service/JwtService.java
xxxxxxxxxxpackage com.planetlearning.jwt.service;import com.auth0.jwt.JWT;import com.auth0.jwt.algorithms.Algorithm;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import java.time.Instant;import java.util.List;public class JwtService { ("${jwt.secret}") private String secretKey; ("${jwt.expiration}") private long expirationTime; public String generateToken(String phoneNumber, List<String> roles) { // 1. Define the algorithm using the secret key Algorithm algorithm = Algorithm.HMAC256(secretKey); // 2. Calculate expiration time Instant now = Instant.now(); Instant expiryDate = now.plusMillis(expirationTime); // 3. Create the token return JWT.create() .withSubject(phoneNumber) // The main identity (Phone Number) .withClaim("roles", roles) // Custom claim: User Roles .withIssuedAt(now) // When was it created? .withExpiresAt(expiryDate) // When does it expire? .sign(algorithm); // Sign it! }}5. Step 5: Create the Controller
Finally, we create a REST Controller to expose an endpoint. This allows users to send a POST request to generate their token.
1. File: src/main/java/com/planetlearning/jwt/controller/AuthController.java
xxxxxxxxxxpackage com.planetlearning.jwt.controller;import com.planetlearning.jwt.dto.TokenRequest;import com.planetlearning.jwt.service.JwtService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import java.util.Map;("/api/auth")public class AuthController { private JwtService jwtService; ("/generate") public ResponseEntity<Map<String, String>> generateToken( TokenRequest request) { // In a real app, you would validate the password/OTP here first! String token = jwtService.generateToken(request.getPhoneNumber(), request.getRoles()); // Return the token in a JSON object return ResponseEntity.ok(Map.of("access_token", token)); }}6. How to Test This?
Now that the code is ready, run your Spring Boot application. We will use Postman to test the API.
http://localhost:8080/api/auth/generate.{
"phoneNumber": "+1234567890",
"roles": ["STUDENT", "PREMIUM_MEMBER"]
}You should receive a 200 OK status code with a generated token:
{
"access_token": " eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIrMTIzNDU2Nzg5MCIsInJvbGVzIjpbIlNUVURFTlQiLCJQUkVNSVVNX01FTUJFUiJdLCJpYXQiOjE3..."
}To confirm the token actually contains the phone number and roles:
access_token string you just received.sub: "+1234567890"roles: ["STUDENT", "PREMIUM_MEMBER"]Congratulations! You have successfully implemented JWT generation using Spring Boot with custom claims.