package _11.asktpk.artisanconnectbackend.security; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.crypto.SecretKey; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @Component public class JwtUtil { @Value("${jwt.secret:defaultSecretKeyNeedsToBeAtLeast32BytesLong}") private String secret; @Value("${jwt.expiration}") private long expiration; // sterowanie tokenami wygasnietymi private final Set blacklistedTokens = ConcurrentHashMap.newKeySet(); public void blacklistToken(String token) { blacklistedTokens.add(token); } public boolean isBlacklisted(String token) { return blacklistedTokens.contains(token); } private SecretKey getSigningKey() { return Keys.hmacShaKeyFor(secret.getBytes()); } private final Map userActiveTokens = new ConcurrentHashMap<>(); public boolean isLatestToken(String token) { String email = extractEmail(token); String tokenId = extractTokenId(token); String latestTokenId = userActiveTokens.get(email); return latestTokenId != null && latestTokenId.equals(tokenId); } public String generateToken(String email, String role, Long userId) { Map claims = new HashMap<>(); claims.put("role", role); claims.put("userId", userId); claims.put("tokenId", UUID.randomUUID().toString()); String token = createToken(claims, email); userActiveTokens.put(email, extractTokenId(token)); return token; } private String createToken(Map claims, String subject) { return Jwts.builder() .setClaims(claims) .setSubject(subject) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + expiration)) .signWith(getSigningKey(), SignatureAlgorithm.HS256) .compact(); } public String extractTokenId(String token) { return extractAllClaims(token).get("tokenId", String.class); } public String extractEmail(String token) { return extractClaim(token, Claims::getSubject); } public String extractRole(String token) { return extractAllClaims(token).get("role", String.class); } public Long extractUserId(String token) { return extractAllClaims(token).get("userId", Long.class); } public T extractClaim(String token, Function claimsResolver) { final Claims claims = extractAllClaims(token); return claimsResolver.apply(claims); } private Claims extractAllClaims(String token) { return Jwts.parserBuilder() .setSigningKey(getSigningKey()) .build() .parseClaimsJws(token) .getBody(); } }