TokenService.java
package api.services;
import java.time.Clock;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import api.dtos.AuthenticationDto;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
/**
* {@link TokenService}.
*/
@Service
public class TokenService {
@Autowired
private Clock clock;
@SuppressWarnings("checkstyle:LineLength")
@Value("${jwt.token.secret:XrLHWXPiznJfz3jvJF9ZJkIzvgC0RAF64dOO8bqSxJ2LStAOUAIO85gWg7tcFlfLL9c6q40UCRKMlwnyM5OQOg==}")
private String secret;
@Value("${jwt.token.expires-minutes:1440}")
private int expiresMinutes;
private JwtParser parser;
/**
* Initialize parser.
*/
@PostConstruct
public void init() {
parser = Jwts.parser()
.clock(() -> Date.from(Instant.now(clock)))
.verifyWith(Keys.hmacShaKeyFor(Base64.getDecoder().decode(secret)))
.build();
}
/**
* Generate new JWT token.
*
* @param authentication User authentication
* @return {@link AuthenticationDto}
*/
public AuthenticationDto generateToken(Authentication authentication) {
String username = authentication.getName();
Instant now = Instant.now(clock);
Date issuedAt = Date.from(now);
Date expireDate = Date.from(now.plus(expiresMinutes, ChronoUnit.MINUTES));
String token = Jwts.builder()
.subject(username)
.issuedAt(issuedAt)
.expiration(expireDate)
.signWith(Keys.hmacShaKeyFor(Base64.getDecoder().decode(secret)))
.compact();
return new AuthenticationDto(token, "Bearer", expireDate);
}
/**
* Get username from JWT token.
*
* @param token JWT token
* @return Username
*/
public String getUsernameByToken(String token) {
try {
return parser.parseSignedClaims(token).getPayload().getSubject();
} catch (ExpiredJwtException e) {
throw new AuthenticationCredentialsNotFoundException("Token is expired");
} catch (Exception e) {
throw new AuthenticationCredentialsNotFoundException("Token is invalid");
}
}
}