Implement token blacklist for JWT logout support
- TokenBlacklistService tracks invalidated tokens using Caffeine cache. - AuthController adds tokens to blacklist on logout. - JwtAuthenticationFilter blocks blacklisted tokens during authentication.
This commit is contained in:
@@ -4,6 +4,9 @@ import com.skycrate.backend.skycrateBackend.dto.LoginRequest;
|
|||||||
import com.skycrate.backend.skycrateBackend.security.JwtService;
|
import com.skycrate.backend.skycrateBackend.security.JwtService;
|
||||||
import com.skycrate.backend.skycrateBackend.entity.User;
|
import com.skycrate.backend.skycrateBackend.entity.User;
|
||||||
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
|
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
|
||||||
|
import com.skycrate.backend.skycrateBackend.security.TokenBlacklistService;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
@@ -48,9 +51,19 @@ public class AuthController {
|
|||||||
return ResponseEntity.ok().body(token);
|
return ResponseEntity.ok().body(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TokenBlacklistService tokenBlacklistService;
|
||||||
|
|
||||||
@PostMapping("/logout")
|
@PostMapping("/logout")
|
||||||
public ResponseEntity<?> logout() {
|
public ResponseEntity<?> logout(HttpServletRequest request) {
|
||||||
// Client-side token deletion (or implement blacklist)
|
String authHeader = request.getHeader("Authorization");
|
||||||
return ResponseEntity.ok("Logged out (client should delete token)");
|
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
|
||||||
|
return ResponseEntity.badRequest().body("Missing or invalid Authorization header");
|
||||||
|
}
|
||||||
|
|
||||||
|
String token = authHeader.substring(7);
|
||||||
|
tokenBlacklistService.blacklistToken(token);
|
||||||
|
|
||||||
|
return ResponseEntity.ok("Logged out successfully");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+13
-1
@@ -20,10 +20,14 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
private final JwtService jwtService;
|
private final JwtService jwtService;
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
|
private final TokenBlacklistService tokenBlacklistService;
|
||||||
|
|
||||||
public JwtAuthenticationFilter(JwtService jwtService, UserRepository userRepository) {
|
public JwtAuthenticationFilter(JwtService jwtService,
|
||||||
|
UserRepository userRepository,
|
||||||
|
TokenBlacklistService tokenBlacklistService) {
|
||||||
this.jwtService = jwtService;
|
this.jwtService = jwtService;
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
|
this.tokenBlacklistService = tokenBlacklistService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -42,6 +46,14 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jwt = authHeader.substring(7);
|
jwt = authHeader.substring(7);
|
||||||
|
|
||||||
|
// Check if token is blacklisted
|
||||||
|
if (tokenBlacklistService.isTokenBlacklisted(jwt)) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||||
|
response.getWriter().write("Token has been blacklisted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
userEmail = jwtService.extractUsername(jwt);
|
userEmail = jwtService.extractUsername(jwt);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
package com.skycrate.backend.skycrateBackend.security;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TokenBlacklistService {
|
||||||
|
|
||||||
|
private final Cache<String, Boolean> blacklistCache;
|
||||||
|
|
||||||
|
public TokenBlacklistService() {
|
||||||
|
this.blacklistCache = Caffeine.newBuilder()
|
||||||
|
.expireAfterWrite(1, TimeUnit.HOURS)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void blacklistToken(String token) {
|
||||||
|
blacklistCache.put(token, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTokenBlacklisted(String token) {
|
||||||
|
return blacklistCache.getIfPresent(token) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user