I am using jose to sign and encrypt JWTs. However I am unable to sign and then encrypt my whole JWT.
I use this function to sign my jwt:
const secretKey = process.env.JWT_SECRET;
const key = new TextEncoder().encode(secretKey);
export async function _encrypt(payload: any) {
return await new SignJWT(payload)
.setProtectedHeader({ alg: "HS256" })
.setIssuedAt()
.setExpirationTime("10 sec from now")
.sign(key);
}
I am using following code to encrypt it (when passing an JWT object it works):
const now = () => (Date.now() / 1000) | 0;
const alg = "dir";
const enc = "A256CBC-HS512";
...
sync function encrypt({
payload,
maxAge,
}: {
payload: JWTPayload;
maxAge: number;
}): Promise<string> {
const secret: Uint8Array = randomBytes(32);
const salt = randomBytes(16);
const encryptionSecret: Uint8Array = await hkdf(
"sha256",
secret,
salt,
"Generated Encryption Key",
32
);
return new EncryptJWT(payload)
.setProtectedHeader({ alg, enc })
.setIssuedAt()
.setExpirationTime(now() + maxAge)
.setJti(crypto.randomUUID())
.encrypt(encryptionSecret);
}
The code does not work as intended because EncryptJWT does only accept an JWT object. This is also reflected in the console: error TypeError: JWT Claims Set MUST be an object
To sign then encrypt you want to use the SignJWT
class to sign and then CompactEncrypt
to encrypt the signed result. An example of this is in https://github.com/panva/jose/issues/112, just replace the key management with your secrets and use appropriate algorithms.