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 Add Dependencies Include the required dependencies in pom.xml: Copy Copy org.springframework.boot spring-boot-starter-security io.jsonwebtoken jjwt 0.11.5 org.springframework.boot spring-boot-starter-web Add JWT Util Create a utility class to generate and validate JWT tokens. Copy Copy 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; } } } Add JWT Filter The filter extracts the JWT token from the request and validates it. Copy Copy 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); } } Add Security Configuration Copy Copy 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

Apr 15, 2025 - 17:45
 0
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:

Copy

Copy

org.springframework.boot
spring-boot-starter-security


io.jsonwebtoken
jjwt
0.11.5


org.springframework.boot
spring-boot-starter-web

  1. Add JWT Util Create a utility class to generate and validate JWT tokens.

Copy

Copy
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;
    }
}

}

  1. Add JWT Filter The filter extracts the JWT token from the request and validates it.

Copy

Copy
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);
}

}

  1. Add Security Configuration

Copy

Copy
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();
}

}

  1. Add Interceptor

Copy

Copy
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;
}

}

  1. Register Interceptors

Copy

Copy
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");
}

}

  1. Create Controller

Copy

Copy
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 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");
    }
}

}

  1. Create Service

Copy

Copy
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserService {
private final Map 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);
}

}

  1. 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!