Search code examples
javascriptspring-bootauthenticationjwttoken

JWT signature verification failing


I am trying to implement my own auth using JWT tokens. I generate the jwt tokens in Java Spring boot.

Im using this website to generate a base64 encoded string to be used as the jwt secret: https://www.devglan.com/online-tools/hmac-sha256-online?ref=blog.tericcabrel.com

This is the relevant Spring boot code:

private Key getSignInKey() {
    byte[] keyBytes = Decoders.BASE64.decode(secretKey);
    return Keys.hmacShaKeyFor(keyBytes);
}
Jwts
        .builder()
        .setClaims(extraClaims)
        .setSubject(userDetails.getUsername())
        .setIssuedAt(new Date(System.currentTimeMillis()))
        .setExpiration(new Date(System.currentTimeMillis() + expiration))
        .signWith(getSignInKey(), SignatureAlgorithm.HS256)
        .compact();

Which works fine, the problem isnt here. The problem arises on the nextjs side where im trying to verify the jwt token i retrieve from the api after logging in:

export async function verifyAuth() {
  const token = cookies().get('user-token')

  if (!token) {
    return null
  }

  const jwtSecretKey = getJwtSecretKey()

  const { payload } = await jwtVerify(token.value, new TextEncoder().encode(jwtSecretKey))

  return payload as JwtPayload
}

This keeps throwing the following exception, allthough im using the same secret key generated by the website above (getJwtSecretKey just returns the env variable from .env and im using jose):

digest: "3414803446"

⨯ JWSSignatureVerificationFailed: signature verification failed

at async verifyAuth (./lib/auth.ts:74:25)

at async Home (./app/page.tsx:11:18)

What am i doing wrong here?


Solution

  • The secret passed in your signing process is decoded from a base64 string before used as the signing secret. You must do the same before passing the secret to jose, otherwise new TextEncoder().encode(jwtSecretKey) just uses the encoded bytes as the secret.

    This in Node.js

    const secret = Buffer.from(jwtSecretKey, 'base64')
    

    Would be the equivalent of

    keyBytes = Decoders.BASE64.decode(secretKey);