auth0 / node-jws

JSON Web Signatures
http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html
MIT License
709 stars 108 forks source link

Async / custom signers and verifiers #103

Open dhensby opened 1 year ago

dhensby commented 1 year ago

Custom (asynchronous) signer/verifier support

When using an external secret store / key management service such as AWS KMS or Azure Key Vault, it is not always possible to have the private key or secret in application memory. Instead, the KMS is used to perform the signing and responds with the signature. As this is an external service it happens asynchronously.

Currently, it is not possible to use these types of asynchronous signing services with the JWS library (at least, not without some circumvention).

Describe the ideal solution

I would like to be able to provide a custom algorithm resolver and to support an asynchronous signer.

The jwsSign opts could take an option that replaces the jwa library for returning a signer/verifier pair. The signer/verifier could then return a Promise that resolves with the signature.

Alternatives and current workarounds

At the moment, the best workaround I can find is to effectively sign the token twice. Once with a random private key that is available in memory and then again using the KMS. The signature from the KMS is then used in place of the one generated in memory.

const { generateKeyPairSync } = require('crypto');
const jws = require('jws');
const keyPair = generateKeyPairSync('rsa', { ... });

async function sign(alg, payload) {
  const signature = jws.sign({
    header: { alg },
    payload,
    secret: keyPair.privateKey,
  });
  const jwsWithoutSig = signature.split('.', 2).join('.');
  const sig = await someAsyncSigner(alg, jwsWithoutSig);
  return `${jwsWithoutSig}.${sig}`;
}

Additional context

There have been other requests around this type of feature and I think the above proposal is the most generic way to achieve the ability to support async signing.

This should address these related issues: #34, #93

I am happy to work on this solution, but it will involve breaking changes as the sign/verify functions will become async instead of sync.