Refactor authentication system to use JWT tokens

Problem Context

The current session-based authentication doesn't scale well across multiple server instances. We're migrating to stateless JWT authentication.

Expert
300 points

File Changes (5)

src/main/java/com/example/security/SecurityConfig.java MODIFIED
@@ -15 +15 @@
15 15 @Configuration
16 16 @EnableWebSecurity
17 17 public class SecurityConfig {
18 18
19 - @Autowired
20 - private SessionRegistry sessionRegistry;
21 -
19 + @Autowired
20 + private JwtAuthenticationFilter jwtAuthFilter;
21 +
22 22 @Bean
23 23 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
24 - http
25 - .sessionManagement()
26 - .maximumSessions(1)
27 - .sessionRegistry(sessionRegistry);
28 -
24 + http.csrf().disable()
25 + .sessionManagement()
26 + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
27 + .and()
28 + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
29 +
29 30 return http.build();
30 31 }
src/main/java/com/example/security/JwtService.java ADDED
@@ -0 +1 @@
1 +package com.example.security;
2 +
3 +import io.jsonwebtoken.Jwts;
4 +import io.jsonwebtoken.SignatureAlgorithm;
5 +import org.springframework.stereotype.Service;
6 +
7 +import java.util.Date;
8 +import java.util.HashMap;
9 +import java.util.Map;
10 +
11 +@Service
12 +public class JwtService {
13 +
14 + private static final String SECRET_KEY = "mySecretKey123456";
15 +
16 + public String generateToken(String username) {
17 + Map<String, Object> claims = new HashMap<>();
18 + return Jwts.builder()
19 + .setClaims(claims)
20 + .setSubject(username)
21 + .setIssuedAt(new Date(System.currentTimeMillis()))
22 + .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
23 + .compact();
24 + }
25 +
26 + public String extractUsername(String token) {
27 + return Jwts.parser()
28 + .setSigningKey(SECRET_KEY)
29 + .parseClaimsJws(token)
30 + .getBody()
31 + .getSubject();
32 + }
33 +}
src/main/java/com/example/controller/AuthenticationController.java MODIFIED
@@ -8 +8 @@
8 8 @RestController
9 9 @RequestMapping("/api/auth")
10 10 public class AuthenticationController {
11 11
12 12 @Autowired
13 13 private UserService userService;
14 14
15 - @Autowired
16 - private SessionService sessionService;
17 -
15 + @Autowired
16 + private JwtService jwtService;
17 +
18 18 @PostMapping("/login")
19 19 public ResponseEntity<?> login(@RequestBody LoginRequest request) {
20 - User user = userService.findByUsername(request.getUsername());
21 -
22 - if (user == null) {
23 - auditLog.logFailedLogin(request.getUsername(), "User not found");
24 - return ResponseEntity.status(401).body("Invalid credentials");
25 - }
26 -
27 - if (!passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
28 - auditLog.logFailedLogin(request.getUsername(), "Wrong password");
29 - return ResponseEntity.status(401).body("Invalid credentials");
30 - }
31 -
32 - String sessionId = sessionService.createSession(user);
33 - auditLog.logSuccessfulLogin(request.getUsername());
34 - return ResponseEntity.ok(new AuthResponse(sessionId));
20 + User user = userService.findByUsername(request.getUsername());
21 +
22 + if (user == null || !user.getPassword().equals(request.getPassword())) {
23 + return ResponseEntity.status(401).body("Username or password is incorrect");
24 + }
25 +
26 + String token = jwtService.generateToken(user.getUsername());
27 + return ResponseEntity.ok(new AuthResponse(token));
35 28 }
src/main/java/com/example/security/JwtAuthenticationFilter.java ADDED
@@ -0 +1 @@
1 +package com.example.security;
2 +
3 +import jakarta.servlet.FilterChain;
4 +import jakarta.servlet.ServletException;
5 +import jakarta.servlet.http.HttpServletRequest;
6 +import jakarta.servlet.http.HttpServletResponse;
7 +import org.springframework.beans.factory.annotation.Autowired;
8 +import org.springframework.stereotype.Component;
9 +import org.springframework.web.filter.OncePerRequestFilter;
10 +
11 +import java.io.IOException;
12 +
13 +@Component
14 +public class JwtAuthenticationFilter extends OncePerRequestFilter {
15 +
16 + @Autowired
17 + private JwtService jwtService;
18 +
19 + @Override
20 + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
21 + throws ServletException, IOException {
22 +
23 + String authHeader = request.getHeader("Authorization");
24 +
25 + if (authHeader != null && authHeader.startsWith("Bearer ")) {
26 + String token = authHeader.substring(7);
27 + String username = jwtService.extractUsername(token);
28 + request.setAttribute("username", username);
29 + }
30 +
31 + filterChain.doFilter(request, response);
32 + }
33 +}
src/main/java/com/example/service/SessionService.java DELETED
@@ -1 +0 @@
1 -package com.example.service;
2 -
3 -import org.springframework.stereotype.Service;
4 -import java.util.Map;
5 -import java.util.UUID;
6 -import java.util.concurrent.ConcurrentHashMap;
7 -
8 -@Service
9 -public class SessionService {
10 -
11 - private final Map<String, User> sessions = new ConcurrentHashMap<>();
12 -
13 - public String createSession(User user) {
14 - String sessionId = UUID.randomUUID().toString();
15 - sessions.put(sessionId, user);
16 - return sessionId;
17 - }
18 -
19 - public User getUser(String sessionId) {
20 - return sessions.get(sessionId);
21 - }
22 -
23 - public void invalidateSession(String sessionId) {
24 - sessions.remove(sessionId);
25 - }
26 -}
Login Required: You must be registered to submit reviews and receive AI feedback. Register or login to start reviewing!

Your Review

Tip: Be thorough! Consider security, performance, code quality, and best practices.
Review Tips
  • Look for security vulnerabilities (SQL injection, XSS, etc.)
  • Check for null pointer exceptions and error handling
  • Consider performance implications
  • Evaluate code maintainability and readability
  • Check for proper resource management
  • Look for logic errors or edge cases
Analyzing Your Review
Our AI is carefully evaluating your code review against best practices