Implementing JWT Authentication in Spring Boot
What is JWT? JSON Web Token (JWT) is a compact, URL-safe token format used for securely transmitting information between parties as a JSON object. JWTs are commonly used for authentication and authorization in web applications, allowing users to securely access protected resources. The token consists of three parts: Header: Contains the token type and signing algorithm. Payload: Holds user claims and metadata. Signature: Ensures token integrity and authenticity. JWTs are stateless, meaning the server does not need to store session information. Instead, the token itself contains the required data, making it a scalable and efficient authentication mechanism. Implementation of JWT in Spring Boot 1. Add Dependencies Include the required dependencies in pom.xml: org.springframework.boot spring-boot-starter-security io.jsonwebtoken jjwt 0.11.5 org.springframework.boot spring-boot-starter-web 2. Add JWT Util Create a utility class to generate and validate JWT tokens. import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; import org.springframework.stereotype.Component; import java.security.Key; import java.util.Date; @Component public class JwtUtil { private final String SECRET_KEY = "your-secret-key-your-secret-key-your-secret-key"; private final long EXPIRATION_TIME = 1000 * 60 * 60; // 1 hour private Key getSigningKey() { return Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); } public String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(getSigningKey(), SignatureAlgorithm.HS256) .compact(); } public String extractUsername(String token) { return Jwts.parserBuilder() .setSigningKey(getSigningKey()) .build() .parseClaimsJws(token) .getBody() .getSubject(); } public boolean validateToken(String token) { try { Jwts.parserBuilder() .setSigningKey(getSigningKey()) .build() .parseClaimsJws(token); return true; } catch (JwtException e) { return false; } } } 3. Add JWT Filter The filter extracts the JWT token from the request and validates it. import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; @Component public class JwtFilter extends OncePerRequestFilter { private final JwtUtil jwtUtil; private final ApplicationContext applicationContext; @Autowired public JwtFilter(JwtUtil jwtUtil, ApplicationContext applicationContext) { this.jwtUtil = jwtUtil; this.applicationContext = applicationContext; } @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 = applicationContext.getBean(CustomUserDetailsService.class).loadUserByUsername(username); if (jwtUtil.validateToken(token)) { UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authToken); } } filterChain.doFilter(request, response); } } 4. Add Security Configuration import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuratio

What is JWT?
JSON Web Token (JWT) is a compact, URL-safe token format used for securely transmitting information between parties as a JSON object. JWTs are commonly used for authentication and authorization in web applications, allowing users to securely access protected resources. The token consists of three parts:
Header: Contains the token type and signing algorithm.
Payload: Holds user claims and metadata.
Signature: Ensures token integrity and authenticity.
JWTs are stateless, meaning the server does not need to store session information. Instead, the token itself contains the required data, making it a scalable and efficient authentication mechanism.
Implementation of JWT in Spring Boot
1. Add Dependencies
Include the required dependencies in pom.xml
:
org.springframework.boot
spring-boot-starter-security
io.jsonwebtoken
jjwt
0.11.5
org.springframework.boot
spring-boot-starter-web
2. Add JWT Util
Create a utility class to generate and validate JWT tokens.
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import java.security.Key;
import java.util.Date;
@Component
public class JwtUtil {
private final String SECRET_KEY = "your-secret-key-your-secret-key-your-secret-key";
private final long EXPIRATION_TIME = 1000 * 60 * 60; // 1 hour
private Key getSigningKey() {
return Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
}
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}
public String extractUsername(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException e) {
return false;
}
}
}
3. Add JWT Filter
The filter extracts the JWT token from the request and validates it.
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class JwtFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
private final ApplicationContext applicationContext;
@Autowired
public JwtFilter(JwtUtil jwtUtil, ApplicationContext applicationContext) {
this.jwtUtil = jwtUtil;
this.applicationContext = applicationContext;
}
@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 = applicationContext.getBean(CustomUserDetailsService.class).loadUserByUsername(username);
if (jwtUtil.validateToken(token)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
4. Add Security Configuration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
public class SecurityConfig {
private final JwtFilter jwtFilter;
public SecurityConfig(JwtFilter jwtFilter) {
this.jwtFilter = jwtFilter;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests()
.requestMatchers("/auth/login").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
5. Add Interceptor
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class JwtInterceptor implements HandlerInterceptor {
private final JwtUtil jwtUtil;
public JwtInterceptor(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
if (jwtUtil.validateToken(token)) {
return true;
}
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}
6. Register Interceptors
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
private final JwtInterceptor jwtInterceptor;
@Autowired
public InterceptorConfig(JwtInterceptor jwtInterceptor) {
this.jwtInterceptor = jwtInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor).excludePathPatterns("/auth/login");
}
}
7. Create Controller
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/auth")
public class AuthController {
private final UserService userService;
private final JwtUtil jwtUtil;
public AuthController(UserService userService, JwtUtil jwtUtil) {
this.userService = userService;
this.jwtUtil = jwtUtil;
}
@PostMapping("/login")
public ResponseEntity> login(@RequestBody Map<String, String> credentials) {
String username = credentials.get("username");
String password = credentials.get("password");
if (userService.authenticate(username, password)) {
String token = jwtUtil.generateToken(username);
return ResponseEntity.ok(Map.of("Bearer", token));
} else {
return ResponseEntity.status(401).body("Invalid Credentials");
}
}
}
8. Create Service
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class UserService {
private final Map<String, String> users = new HashMap<>();
public UserService() {
users.put("admin", "password");
}
public boolean authenticate(String username, String password) {
return users.containsKey(username) && users.get(username).equals(password);
}
}
9. Testing
Send a POST request to
/auth/login
with a valid username and password.If successful, it returns a JWT token.
Use this token in the Authorization header (
Bearer
) when making requests to secured endpoints.
Now your Spring Boot app supports JWT authentication with proper security configurations!