Moved contents from ./Backend/src/ to ./src/
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
package com.skycrate.backend.skycrateBackend.security;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.*;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
|
||||
public class EncryptionService {
|
||||
|
||||
private static final int KEY_LENGTH = 256;
|
||||
private static final int ITERATIONS = 65536;
|
||||
private static final int SALT_LENGTH = 16;
|
||||
private static final int IV_LENGTH = 12;
|
||||
|
||||
public static byte[] generateSalt() {
|
||||
byte[] salt = new byte[SALT_LENGTH];
|
||||
new SecureRandom().nextBytes(salt);
|
||||
return salt;
|
||||
}
|
||||
|
||||
public static SecretKey deriveKey(String password, byte[] salt) throws Exception {
|
||||
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_LENGTH);
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] plaintext, SecretKey key, byte[] iv) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
|
||||
return cipher.doFinal(plaintext);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] ciphertext, SecretKey key, byte[] iv) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
GCMParameterSpec spec = new GCMParameterSpec(128, iv);
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
||||
return cipher.doFinal(ciphertext);
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package com.skycrate.backend.skycrateBackend.security;
|
||||
|
||||
import com.skycrate.backend.skycrateBackend.repository.UserRepository;
|
||||
import com.skycrate.backend.skycrateBackend.entity.User;
|
||||
import com.skycrate.backend.skycrateBackend.services.JwtService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
private final JwtService jwtService;
|
||||
private final UserRepository userRepository;
|
||||
private final TokenBlacklistService tokenBlacklistService;
|
||||
|
||||
public JwtAuthenticationFilter(JwtService jwtService,
|
||||
UserRepository userRepository,
|
||||
TokenBlacklistService tokenBlacklistService) {
|
||||
this.jwtService = jwtService;
|
||||
this.userRepository = userRepository;
|
||||
this.tokenBlacklistService = tokenBlacklistService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
String path = request.getRequestURI();
|
||||
if (path.startsWith("/api/auth") || path.startsWith("/actuator")) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
final String authHeader = request.getHeader("Authorization");
|
||||
final String jwt;
|
||||
final String username;
|
||||
|
||||
if (!StringUtils.hasText(authHeader) || !authHeader.startsWith("Bearer ")) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
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 {
|
||||
username = jwtService.extractUsername(jwt); // This is actually the `username`, not email
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.getWriter().write("Invalid JWT token");
|
||||
return;
|
||||
}
|
||||
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
// ❗ Use username to find the user
|
||||
User user = userRepository.findByUsername(username).orElse(null);
|
||||
|
||||
if (user != null && jwtService.isTokenValid(jwt, user)) {
|
||||
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
|
||||
user, null, user.getAuthorities());
|
||||
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||
} else {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.getWriter().write("Expired or invalid JWT");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
+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