Stanleyy
Stanleyy

Reputation: 348

NextJs middleware can't verify JWT from java spring backend

Im using Nextjs mainly for my frontend and Java springboot for my backend. However I want to use the nextjs middleware for protecting my routes via JWT. Since jsonwebtoken can't run on edge functions I am using jose.

After attempting to grab the JWT from cookies, I try to verify it and get this message:

JWSSignatureVerificationFailed: signature verification failed

Here is the signing of my token in the spring backend:

public static String generateJwtToken(AppUser user) {
        Map<String, Object> claims = new HashMap<>();

        return Jwts.builder()
            .setClaims(claims)
            .setSubject(user.getUsername())
            .setIssuedAt(new Date(System.currentTimeMillis()))
            .setExpiration(new Date(System.currentTimeMillis() + TOKEN_VALIDITY * 1000))
            .signWith(SignatureAlgorithm.HS512, jwtSecret)
            .compact(); 
    }

and here is the attempt to verify it in my nextjs middleware file:

  const token = request.cookies.get('jwt');

  const { payload } = await jwtVerify(
    token,
    new TextEncoder().encode(process.env.SECRET_KEY)
  );

Note: the jwtSecret and SECRET_KEY are the exact same values coming from the exact same .env file. Any help would be greatly appreciated

Upvotes: 1

Views: 646

Answers (2)

Alexis Landin
Alexis Landin

Reputation: 11

DISCLAIMER: Be sure to know the security implication of sending your secret key as a String and not as byte array.

Based on @juliomalves response and his linked github issue, i made a slight change.

My backend response was set in a Cookie header and i didn't want to parse and send it as bytes to my frontend (because i use that Cookie to get the jwt token and send it back to the backend in other request to do authorization).

So, if you want to keep the key as an String and encode it in your middleware you can make it this way:

const base64Key = Buffer.from(YOUR_STRING_SECRET_KEY,'base64'));

Then you can verify as you were doing previously with jwtVerify

  const { payload } = await jwtVerify(
    token,
    base64key
  );

Upvotes: 1

Stanleyy
Stanleyy

Reputation: 348

Found my answer more or less here https://github.com/auth0/node-jsonwebtoken/issues/208#issuecomment-231861138. This exact comment explains what should be happening with the secret key.

As for what I fixed in the code, I had to return the secret key as a bytes array.

.signWith(SignatureAlgorithm.HS512, jwtSecret.getBytes("UTF-8"))

Upvotes: 2

Related Questions