Table of Contents
In today's digital landscape, securing your Spring Boot applications is more critical than ever. With the increasing sophistication of cyber threats in 2026, implementing robust authentication mechanisms is essential for protecting user data and maintaining trust. This step-by-step guide walks you through the process of implementing secure authentication in your Spring Boot project.
Prerequisites
- Java Development Kit (JDK) 17 or higher installed
- Spring Boot 3.x project setup
- Maven or Gradle build tool
- Basic understanding of Spring Security
- Database setup (e.g., MySQL, PostgreSQL)
Step 1: Add Dependencies
Include the necessary dependencies in your build configuration to enable Spring Security and JWT support.
For Maven:
<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.2</version>
</dependency>
Step 2: Configure User Details Service
Create a service to load user-specific data during authentication.
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
getAuthorities(user)
);
}
private Collection<GrantedAuthority> getAuthorities(User user) {
return user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
}
}
Step 3: Implement JWT Utility Class
Handle token creation and validation with a utility class.
@Component
public class JwtUtil {
private String SECRET_KEY = "your-256-bit-secret";
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
private Boolean isTokenExpired(String token) {
final Date expiration = extractClaim(token, Claims::getExpiration);
return expiration.before(new Date());
}
public T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
}
Step 4: Configure Spring Security
Set up security configurations to integrate JWT authentication.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Step 5: Create Authentication Controller
Handle login requests and token issuance.
@RestController
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/authenticate")
public ResponseEntity<Map<String, String>> createAuthenticationToken(@RequestBody AuthenticationRequest authRequest) throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
);
} catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
}
final UserDetails userDetails = userDetailsService.loadUserByUsername(authRequest.getUsername());
final String jwt = jwtUtil.generateToken(userDetails);
Map<String, String> response = new HashMap<>();
response.put("jwt", jwt);
return ResponseEntity.ok(response);
}
}
Step 6: Create JWT Request Filter
This filter intercepts requests to validate JWT tokens.
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
try {
username = jwtUtil.extractUsername(jwt);
} catch (Exception e) {
// Invalid token
}
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}
Conclusion
By following these steps, you can implement a secure JWT-based authentication system in your Spring Boot application for 2026. Regularly update dependencies and review security best practices to stay ahead of emerging threats.