Got Stuck with Error. JWT validity cannot be asserted and should not be trusted

74 Views Asked by At

My JwtUtil.java code:

@Service
@RequiredArgsConstructor
public class JwtUtil {



    private SecretKey getSigningKey() {
        return Jwts.SIG.HS512.key().build();
    }

    public String generateToken(SecurityMember securityMember) {
        Map<String, Object> claims = new HashMap<>();
        return createToken(claims, securityMember.getUsername());
    }

    public String createToken(Map<String, Object> claims, String subject) {
        return Jwts.builder().claims(claims).subject(subject).issuedAt(new Date(System.currentTimeMillis()))
                .expiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
                .signWith(getSigningKey())
                .compact();
    }

    public Boolean validateToken(String token, SecurityMember securityMember) {
        final String username = extractUserName(token);
        return (username.equals(securityMember.getUsername()) && !isTokenExpired(token));
    }

    private boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date(System.currentTimeMillis()));
    }

    public Date extractExpiration(String token) {
        return extractClaims(token,Claims::getExpiration);
    }

    public
    String extractUserName(String token) {
        return extractClaims(token,Claims::getSubject);
    }


    private <T> T extractClaims(String token, Function<Claims, T> claimsResolver) {
        final Jwe<Claims> claims = extractAllClaims(token);
        return claimsResolver.apply(claims.getPayload());
    }

    private Jwe<Claims> extractAllClaims(String token) {
        try {
            return Jwts.parser()
                            .requireIssuer("http://localhost:8080")
                            .verifyWith(getSigningKey())
                            .build()
                            .parse(token).accept(Jwe.CLAIMS);
        } catch (JwtException ex) {
            throw new JwtException("WRONG JWT"+ex.getMessage(),ex);
        }


    }
}

The Problem is:

Caused by: io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.

2

There are 2 best solutions below

0
jps On

Your function getSigningKey() uses Jwts.SIG.HS512.key().build();, which creates a new key every time you call it.

But you call getSigningKey() when you sign the token and when you verify it, so you have different keys in both cases.

Instead create a key and store it and use the stored key. E.g:

signingKey = getSigningKey();

// use it for signing
Jwts.builder().signWith(signingKey)...

// and verification
Jwts.parser().verifyWith(signingKey)...

But the creation of the key should not happen everytime you create a token but be detached from that. You should also consider persisting the key, so that you still have the same key after restarting the program. Otherwise all issued tokens would become invalid after a restart.

Verification means that you verify the token signature against the same key that was used to sign it.

1
StevenCanDrink On

in my case i fix it implement

  private SecretKey secretKey;
  private SecretKey getSigningKey() {
             this.secretKey = Jwts.SIG.HS512.key().build();
        return secretKey;
    }

  private Jwe<Claims> extractAllClaims(String token) {
    try {
        return Jwts.parser()
                        .requireIssuer("http://localhost:8080")
                        .verifyWith(secretKey)
                        .build()
                        .parse(token).accept(Jwe.CLAIMS);
    } catch (JwtException ex) {
        throw new JwtException("WRONG JWT"+ex.getMessage(),ex);
    }