JwtService.java
package com.distasilucas.cryptobalancetracker.service;
import com.distasilucas.cryptobalancetracker.exception.ApiException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.function.Function;
import static com.distasilucas.cryptobalancetracker.constants.Constants.UNKNOWN_ERROR;
import static com.distasilucas.cryptobalancetracker.constants.ExceptionConstants.TOKEN_EXPIRED;
@Slf4j
@Service
@ConditionalOnProperty(prefix = "security", name = "enabled", havingValue = "true")
public class JwtService {
public final String jwtSigningKey;
public JwtService(@Value("${jwt.signing-key}") String jwtSigningKey) {
this.jwtSigningKey = jwtSigningKey;
}
public boolean isTokenValid(String token, UserDetails userDetails) {
log.info("Validating JWT token for {}", userDetails.getUsername());
return isTokenNonExpired(token) && extractUsername(token).equals(userDetails.getUsername());
}
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
private boolean isTokenNonExpired(String token) {
var date = extractClaim(token, Claims::getExpiration);
return date.after(new Date());
}
private <T> T extractClaim(String token, Function<Claims, T> claims) {
Claims claim = extractClaims(token);
return claims.apply(claim);
}
private Claims extractClaims(String token) {
try {
return Jwts.parser()
.verifyWith(getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload();
} catch (ExpiredJwtException ex) {
throw new ApiException(HttpStatus.BAD_REQUEST, TOKEN_EXPIRED);
} catch (Exception ex) {
log.info("Exception when parsing JWT Token {}", ex.getMessage());
throw new ApiException(UNKNOWN_ERROR, ex);
}
}
private SecretKey getSigningKey() {
var decoders = Decoders.BASE64.decode(jwtSigningKey);
return Keys.hmacShaKeyFor(decoders);
}
}