Spring Security & JWT Auth
Spring Security is a powerful, highly customizable authentication and authorization framework. Combined with JWT (JSON Web Tokens), it enables stateless REST API security without sessions.
1 Security Configuration
Java — SecurityConfig.java
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthFilter jwtAuthFilter;
private final UserDetailsService userDetailsService;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) // Disabled for stateless APIs
.sessionManagement(s -> s.sessionCreationPolicy(STATELESS))
.authorizeHttpRequests(auth -> auth
// Public endpoints
.requestMatchers(POST, "/api/v1/auth/**").permitAll()
.requestMatchers(GET, "/api/v1/products/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
// Protected endpoints
.requestMatchers("/api/v1/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
// Add JWT filter before username/password filter
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Bean
public AuthenticationManager authManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
}
2 JWT Filter & Token Service
Java — JwtAuthFilter.java
@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
String jwt = authHeader.substring(7);
String username = jwtService.extractUsername(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails user = userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(jwt, user)) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
3 Code Challenge
Challenge: Implement a complete auth flow:
POST /auth/register creates a user and returns tokens, POST /auth/login validates credentials and returns access + refresh tokens, and POST /auth/refresh validates the refresh token and returns a new access token.