I am struggling to understand how to use the npm jose module (https://www.npmjs.com/package/jose) to create and verify signed JWT tokens in my Node application. My scenario is this: I want to sign an authenticated request to access a resource. I can successfully create a JWT claim for this request grant token that respects the properties of “its” and “aud”, “exp”, etc. but I want to sign it (to wit, using the SignJWT object and the ‘sign’ method) so that when it gets passed back to my server as a request I can validate it and grant or reject access. The “sign” method doesn’t seem to like anything I pass it for the ‘key’ parameter (I am not passing any options — maybe I should be, but what?). I am attempting to use RSA key pairs. I want to sign with the private key and verify with the public key. For my immediate need, I suppose I could use a symmetric key instead, but I am thinking of some other future scenarios where I will want this classic PKCS relationship of certificate keys. And at any rate, I don’t think this choice has anything to do with the current roadblock to my progress. I first tried to use jose/util/generate_key_pair to create my public/private pair. But when I went to use the key, the error informed me this was not supported by my implementation. So I switched to trying to create a ‘pem’ cert outside of my app and applying that (as text), but that also failed. The ‘sign’ method reports that the key must be a ‘KeyLike’, ‘CryptoKey’, or ‘Uint8Array’ type. Well, the UInt8Array (node buffer) is not enough type information: it doesn’t speak to what is in that buffer, and “KeyLike” is such a vague definition that it’s ignorable. After beseeching the oracles of the search engines, I found I could create a key pair in CryptoKey format using the following from Node APIs:
crypto.webcrypto.subtle.generateKey(
{
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256"
},
true,
[‘sign’, ‘verify’]
).then((pair:any) => {
serverInstance.keyPair = pair
})
But, still, when I get to the signing part:
siaToken.sign(serverInstance.keyPair.privateKey).then(signature => {
I get an exception that reports “TypeError: CryptoKey does not support this operation”
Thinking this might have to do with the ‘usages’ parameter of generateKey, I tried various values there, but with no success.
So, I am flummoxed. Can anyone tell me how to (a) best produce a pair of keys for this purpose and (b) how to apply these for JWT signing?