package net.moustos.mtgsearch.security; import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTVerificationException; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.time.Instant; import java.time.temporal.ChronoUnit; /** * JWT Token provider for generating and validating JWT tokens */ @Component public class JwtTokenProvider { @Value("${app.jwt.secret:your-secret-key-change-in-production}") private String jwtSecret; @Value("${app.jwt.expiration:86400}") private long jwtExpiration; private static final String CLAIM_USER_ID = "userId"; private static final String CLAIM_USERNAME = "username"; private static final String CLAIM_EMAIL = "email"; /** * Generate a JWT token for a user */ public String generateToken(long userId, String username, String email) { Instant now = Instant.now(); Instant expiresAt = now.plus(jwtExpiration, ChronoUnit.SECONDS); return JWT.create() .withClaim(CLAIM_USER_ID, userId) .withClaim(CLAIM_USERNAME, username) .withClaim(CLAIM_EMAIL, email) .withIssuedAt(now) .withExpiresAt(expiresAt) .withIssuer("mtg-search") .sign(Algorithm.HMAC256(jwtSecret)); } /** * Validate JWT token and extract user ID */ public long validateTokenAndGetUserId(String token) throws JWTVerificationException { return JWT.require(Algorithm.HMAC256(jwtSecret)) .withIssuer("mtg-search") .build() .verify(token) .getClaim(CLAIM_USER_ID) .asLong(); } /** * Validate JWT token and extract username */ public String validateTokenAndGetUsername(String token) throws JWTVerificationException { return JWT.require(Algorithm.HMAC256(jwtSecret)) .withIssuer("mtg-search") .build() .verify(token) .getClaim(CLAIM_USERNAME) .asString(); } /** * Validate JWT token */ public boolean validateToken(String token) { try { JWT.require(Algorithm.HMAC256(jwtSecret)) .withIssuer("mtg-search") .build() .verify(token); return true; } catch (JWTVerificationException e) { return false; } } }