package wtf.beatrice.releasehive.services; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import wtf.beatrice.releasehive.models.User; import javax.crypto.SecretKey; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.function.Function; @Service public class JWTService { @Value("${security.jwt.secret-key}") private String secretKey; @Value("${security.jwt.expiration-time}") private long jwtExpiration; public String extractEmail(String token) { return extractClaim(token, Claims::getSubject); } public T extractClaim(String token, Function claimsResolver) { final Claims claims = extractAllClaims(token); return claimsResolver.apply(claims); } public String generateToken(User userDetails) { return generateToken(new HashMap<>(), userDetails); } public String generateToken(Map extraClaims, User userDetails) { return buildToken(extraClaims, userDetails, jwtExpiration); } public long getExpirationTime() { return jwtExpiration; } private String buildToken( Map extraClaims, User userDetails, long expiration ) { return Jwts .builder() .claims(extraClaims) .subject(userDetails.getEmail()) .issuedAt(new Date(System.currentTimeMillis())) .expiration(new Date(System.currentTimeMillis() + expiration)) .signWith(getSignInKey(), Jwts.SIG.HS256) .compact(); } public boolean isTokenValid(String token, User userDetails) { final String email = extractEmail(token); return (email.equals(userDetails.getEmail())) && !isTokenExpired(token); } private boolean isTokenExpired(String token) { return extractExpiration(token).before(new Date()); } private Date extractExpiration(String token) { return extractClaim(token, Claims::getExpiration); } private Claims extractAllClaims(String token) { return Jwts .parser() .verifyWith(getSignInKey()) .build() .parseSignedClaims(token) .getPayload(); } private SecretKey getSignInKey() { byte[] keyBytes = Decoders.BASE64.decode(secretKey); return Keys.hmacShaKeyFor(keyBytes); } }