VOOZH about

URL: https://www.javacodegeeks.com/2025/05/how-to-secure-rest-apis-with-spring-security-and-jwt-2025-edition.html

⇱ How to Secure REST APIs with Spring Security and JWT (2025 Edition) - Java Code Geeks


In 2025, stateless authentication remains the go-to approach for securing REST APIs. Spring Security combined with JWT (JSON Web Tokens) continues to be a powerful, scalable solution — but the practices around token handling, refresh flows, and endpoint protection have evolved.

This guide walks you through securing your Spring Boot REST APIs using Spring Security and JWT, with updated approaches for 2025.

⚙️ Why JWT for REST API Security?

JWT enables stateless authentication, eliminating the need for session storage. It allows clients to carry the user’s identity and permissions in an encrypted token.

Benefits:

  • Stateless = scalable across microservices
  • Easy integration with frontend/mobile clients
  • Self-contained (no DB lookups needed for each request)

🧱 Project Setup (Spring Boot 3.2+)

Make sure you’re using:

  • Java 21+
  • Spring Boot 3.2+
  • Spring Security 6+
  • jjwt or nimbus-jose-jwt for token handling

Add dependencies (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.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>

🔐 Creating the JWT Utility Class

@Component
public class JwtService {

 private final String secretKey = "your-256-bit-secret-key";
 private final Duration expiration = Duration.ofMinutes(15);

 public String generateToken(String username) {
 return Jwts.builder()
 .setSubject(username)
 .setIssuedAt(new Date())
 .setExpiration(Date.from(Instant.now().plus(expiration)))
 .signWith(Keys.hmacShaKeyFor(secretKey.getBytes()), SignatureAlgorithm.HS256)
 .compact();
 }

 public String extractUsername(String token) {
 return Jwts.parserBuilder()
 .setSigningKey(secretKey.getBytes())
 .build()
 .parseClaimsJws(token)
 .getBody()
 .getSubject();
 }

 public boolean isValid(String token) {
 try {
 return !extractExpiration(token).before(new Date());
 } catch (JwtException e) {
 return false;
 }
 }

 private Date extractExpiration(String token) {
 return Jwts.parserBuilder()
 .setSigningKey(secretKey.getBytes())
 .build()
 .parseClaimsJws(token)
 .getBody()
 .getExpiration();
 }
}

🛡️ Configuring Spring Security with JWT Authentication Filter

@Configuration
@EnableWebSecurity
public class SecurityConfig {

 @Autowired
 private JwtAuthenticationFilter jwtFilter;

 @Bean
 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
 return http
 .csrf(AbstractHttpConfigurer::disable)
 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
 .authorizeHttpRequests(auth -> auth
 .requestMatchers("/api/auth/**").permitAll()
 .anyRequest().authenticated())
 .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
 .build();
 }
}

JWT Filter:

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

 @Autowired
 private JwtService jwtService;

 @Override
 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
 throws ServletException, IOException {

 final String authHeader = request.getHeader("Authorization");
 if (authHeader == null || !authHeader.startsWith("Bearer ")) {
 filterChain.doFilter(request, response);
 return;
 }

 final String token = authHeader.substring(7);
 if (jwtService.isValid(token)) {
 String username = jwtService.extractUsername(token);
 UsernamePasswordAuthenticationToken auth =
 new UsernamePasswordAuthenticationToken(username, null, List.of());
 SecurityContextHolder.getContext().setAuthentication(auth);
 }

 filterChain.doFilter(request, response);
 }
}

🔁 Refresh Token Flow (2025 Best Practices)

To keep your JWTs short-lived (15 minutes or less), use a refresh token stored securely (e.g., HTTP-only cookie or secure local storage).

Sample Refresh Endpoint

@PostMapping("/api/auth/refresh")
public ResponseEntity<TokenResponse> refresh(@RequestBody RefreshRequest request) {
 String refreshToken = request.getRefreshToken();
 // Validate refresh token from DB or cache
 if (!refreshTokenService.isValid(refreshToken)) {
 return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
 }

 String newAccessToken = jwtService.generateToken(request.getUsername());
 return ResponseEntity.ok(new TokenResponse(newAccessToken));
}

🧠 Tips for Production Security in 2025

  1. Use short-lived access tokens (≤ 15 mins)
  2. Use long-lived refresh tokens (7–30 days), stored securely
  3. Enable CORS and CSRF protection appropriately for SPAs
  4. Add IP/device metadata checks for refresh flows
  5. Implement token revocation logic (DB, cache, or blacklist)
  6. Use HTTPS exclusively

🧪 Testing with Postman or Curl

Login Request:

curl -X POST http://localhost:8080/api/auth/login \
 -H "Content-Type: application/json" \
 -d '{"username":"john", "password":"password"}'

Authenticated Request:

curl http://localhost:8080/api/user/profile \
 -H "Authorization: Bearer <access_token>"

📚 Further Reading & Tools

✅ Conclusion

Securing REST APIs with JWT and Spring Security in 2025 means prioritizing stateless design, short-lived access tokens, and safe refresh token flows. With the latest Spring Security features, this setup is both powerful and clean — ready to scale with your modern web applications.

Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

👁 Photo of Eleftheria Drosopoulou
Eleftheria Drosopoulou
May 20th, 2025Last Updated: May 16th, 2025
0 3,291 2 minutes read

Eleftheria Drosopoulou

Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button
Close
wpDiscuz