0

How do I create a NodeJS Crypto KeyObject from the randomish string in my .env file?

I was using jsonwebtoken to create/verify JWTs, but it can't run in nextjs middleware edge functions, so I want to migrate to using jose. The problem is that in jose you can't sign a JWT with a secret string from your .env file, you need to create a cryptographic KeyObject and use that to sign the JWT.

// example env file
JWT_SECRET=Swe4g7c?UBm5Nrd96vhsVDtkyJFbqKMTm!TMw5BDRLtaCFAXNvbq?s4rGKQSZnUP

I tried to create a KeyObject with the API below, but I got an error from jose:

import crypto from 'crypto'; 
const key = crypto.createSecretKey(process.env.JWT_SECRET, 'utf-8'); 
const jwt = new jose.SignJWT(payload).sign(key); 

// Error: KeyObject or CryptoKey instance for asymmetric algorithms must not be of type "secret."

I also tried to use a Uint8Array, since the jose docs say I can, but I get this error:

const key = new TextEncoder().encode(process.env.JWT_SECRET);
const jwt = new jose.SignJWT(payload).sign(key); 

// Error: Key must be one of type KeyObject or CryptoKey. Received an instance of Uint8Array.`

Thanks in advance for any help, comments, links, resources!

TJBlackman
  • 1,895
  • 3
  • 20
  • 46

1 Answers1

6

The only thing you're missing is setting the JOSE protected header with an appropriate symmetric JWS algorithm (alg).

The example show how that's done and the appropriate symmetric algorithm is HS256.

import * as jose from "jose";

const secret = new TextEncoder().encode(
  "Swe4g7c?UBm5Nrd96vhsVDtkyJFbqKMTm!TMw5BDRLtaCFAXNvbq?s4rGKQSZnUP"
);

const jwt = await new jose.SignJWT({ foo: "bar" })
  .setProtectedHeader({ alg: "HS256" })
  .sign(secret);
console.log(jwt); // eyJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.iPFY1ibZc5dTBzRD46ma-Du0avf20nYKtQQsgnyf7ZM
  • Thank you! Your example link shows an example using `ES256`, not `HS256`, so I'm wondering how you found that option. I was using ES256, and it obviously was not working. – TJBlackman May 26 '22 at 14:26
  • I found this demo on a Vercel Github page that shows the implementation I was/am trying to accomplish: https://github.com/vercel/examples/blob/main/edge-functions/jwt-authentication/lib/auth.ts – TJBlackman May 26 '22 at 15:25
  • 2
    Final note: To anyone running this in a NextJS middleware (edge function), crypto is not supported (at least, not right now). Use the TextEncoder to create a Uint8Array. – TJBlackman May 26 '22 at 15:36
  • 1
    Those are standard JOSE algorithm identifiers. [here](https://github.com/panva/jose/issues/114) a general overview. [here](https://github.com/panva/jose/issues/210) algorithm specific requirements on the key/secret. None of this is proprietary to the `jose` library, it merely implements the JOSE family of specifications. –  May 26 '22 at 16:29