Skip to content

Async / custom signers and verifiers #103

@dhensby

Description

@dhensby

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions