Introduction
JWT (JSON Web Token) is a secure method for authenticating users in modern applications. Instead of storing session data on the server, JWT stores authentication information inside a token. This token is shared between the client and server, enabling a fast, secure, and scalable authentication process. In this article, we will learn how JWT authentication works and how to implement it step by step in a Spring Boot application, using simple, beginner-friendly language.
What is JWT?
JWT (JSON Web Token) is a compact, secure token used to verify a user's identity. It is commonly used in REST APIs.
A JWT has 3 parts:
Header – contains signing algorithm
Payload – contains user information
Signature – verifies token integrity
Example JWT structure:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Why Use JWT in Spring Boot?
JWT is popular because:
It is stateless (no session storage needed)
It works well for distributed systems
It is fast and secure
It supports mobile and web clients easily
Spring Boot + JWT is widely used in India for e-commerce apps, banking systems, and internal employee portals.
Step 1: Add Dependencies
Add Spring Security and JWT dependencies in pom.xml.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
Step 2: Create a JWT Utility Class
This class will generate and validate tokens.
@Component
public class JwtUtil {
private final String SECRET = "mysecretkey";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateToken(String token, UserDetails userDetails) {
String username = extractUsername(token);
return username.equals(userDetails.getUsername());
}
}
Step 3: Create a JWT Authentication Filter
This filter checks the token for each request.
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
String token = null;
String username = null;
if (authHeader != null && authHeader.startsWith("Bearer ")) {
token = authHeader.substring(7);
username = jwtUtil.extractUsername(token);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
Step 4: Configure Spring Security
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtFilter jwtFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Step 5: Create Authentication API
This API validates the user and returns the JWT token.
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/authenticate")
public String authenticate(@RequestBody AuthRequest authRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword()));
} catch (Exception e) {
throw new Exception("Invalid username or password");
}
return jwtUtil.generateToken(authRequest.getUsername());
}
}
Step 6: Testing the Flow
Call /authenticate with username and password
Receive the JWT token
Send the token in header for every request:
Authorization: Bearer <token>
Spring Boot validates token using the filter
Real-Life Example
A banking app in India uses JWT for secure login. Every time a user logs in, they get a token. All future API calls—balance check, fund transfer, statements—use this token. This prevents unauthorized access and protects sensitive financial data.
Best Practices
Store secret keys securely
Use long and complex JWT secrets
Set token expiration time
Refresh tokens periodically
Use HTTPS in production
Summary
JWT authentication in Spring Boot provides a secure and scalable way to protect REST APIs. By generating tokens, validating them, and integrating with Spring Security, developers can create robust authentication systems for web and mobile applications. JWT is widely used in modern backend systems due to its speed, stateless architecture, and flexibility.