content: package io.aiven.klaw.clusterapi.services;
  
  import io.jsonwebtoken.Claims;
  import io.jsonwebtoken.Jws;
  import io.jsonwebtoken.Jwts;
  import io.jsonwebtoken.SignatureAlgorithm;
  import java.security.Key;
  import java.util.Date;
  import java.util.function.Function;
  import javax.crypto.spec.SecretKeySpec;
  import org.apache.tomcat.util.codec.binary.Base64;
  import org.springframework.beans.factory.InitializingBean;
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.stereotype.Service;
  
  @Service
  public class JwtTokenUtilService implements InitializingBean {
    @Value("${klaw.clusterapi.access.base64.secret}")
    private String clusterApiSecret;
  
    private static byte[] decodedSecret;
  
    // retrieve username from jwt token
    public String getUsernameFromToken(String token) {
      return getClaimFromToken(token, Claims::getSubject);
    }
  
    // retrieve expiration date from jwt token
    private Date getExpirationDateFromToken(String token) {
      return getClaimFromToken(token, Claims::getExpiration);
    }
  
    private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
      final Claims claims = getAllClaimsFromToken(token);
      return claimsResolver.apply(claims);
    }
  
    // for retrieving any information from token we will need the secret key
    private Claims getAllClaimsFromToken(String token) {
      Key hmacKey = new SecretKeySpec(decodedSecret, SignatureAlgorithm.HS256.getJcaName());
      Jws<Claims> jwt = Jwts.parser().setSigningKey(hmacKey).build().parseClaimsJws(token);
      return jwt.getBody();
    }
  
    // check if the token has expired
    private Boolean isTokenExpired(String token) {
      final Date expiration = getExpirationDateFromToken(token);
      return expiration.before(new Date());
    }
  
    // validate token
    public Boolean validateToken(String token) {
      return !isTokenExpired(token);
    }
  
    // validate secret during app initialization
    @Override
    public void afterPropertiesSet() throws Exception {
      if (clusterApiSecret != null && !clusterApiSecret.trim().equals("")) {
        try {
          decodedSecret = Base64.decodeBase64(clusterApiSecret);
          return;
        } catch (Exception e) {
          throw new Exception(
              "Invalid Base64 value configured. klaw.clusterapi.access.base64.secret");
        }
      }
      throw new Exception("Property not configured. klaw.clusterapi.access.base64.secret");
    }
  }
  