auth0/node-jsonwebtoken · error

"alg" parameter "${algorithm}" requires curve "${allowedCurv

Error message

"alg" parameter "${algorithm}" requires curve "${allowedCurve}".

What it means

For EC keys, each ES* algorithm mandates a specific NIST curve (ES256 -> P-256, ES384 -> P-384, ES512 -> P-521). jsonwebtoken compares the key's asymmetricKeyDetails.namedCurve against the required curve and throws when they differ, since Node's crypto would otherwise produce a mismatched/invalid signature length.

Source

Thrown at lib/validateAsymmetricKey.js:46

  if (!allowedAlgorithms.includes(algorithm)) {
    throw new Error(`"alg" parameter for "${keyType}" key type must be one of: ${allowedAlgorithms.join(', ')}.`)
  }

  /*
   * Ignore the next block from test coverage because it gets executed
   * conditionally depending on the Node version. Not ignoring it would
   * prevent us from reaching the target % of coverage for versions of
   * Node under 15.7.0.
   */
  /* istanbul ignore next */
  if (ASYMMETRIC_KEY_DETAILS_SUPPORTED) {
    switch (keyType) {
    case 'ec':
      const keyCurve = key.asymmetricKeyDetails.namedCurve;
      const allowedCurve = allowedCurves[algorithm];

      if (keyCurve !== allowedCurve) {
        throw new Error(`"alg" parameter "${algorithm}" requires curve "${allowedCurve}".`);
      }
      break;

    case 'rsa-pss':
      if (RSA_PSS_KEY_DETAILS_SUPPORTED) {
        const length = parseInt(algorithm.slice(-3), 10);
        const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails;

        if (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm) {
          throw new Error(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${algorithm}.`);
        }

        if (saltLength !== undefined && saltLength > length >> 3) {
          throw new Error(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${algorithm}.`)
        }
      }
      break;
    }

View on GitHub (pinned to b924272f29)

Solutions

  1. Regenerate the key with the matching curve: crypto.generateKeyPairSync('ec', { namedCurve: 'P-256' }) for ES256 ('P-384' for ES384, 'P-521' for ES512)
  2. Or change the algorithm to match the existing curve (P-384 key -> ES384)
  3. Check the curve with key.asymmetricKeyDetails.namedCurve before signing

Example fix

// before
const { privateKey } = crypto.generateKeyPairSync('ec', { namedCurve: 'secp256k1' });
jwt.sign(payload, privateKey, { algorithm: 'ES256' });
// after
const { privateKey } = crypto.generateKeyPairSync('ec', { namedCurve: 'P-256' });
jwt.sign(payload, privateKey, { algorithm: 'ES256' });
Defensive patterns

Strategy: validation

Validate before calling

const curveForAlg = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' };
function ecCurveMatches(alg, key) {
  if (!/^ES/.test(alg)) return true;
  return key.asymmetricKeyDetails?.namedCurve === curveForAlg[alg];
}
if (!ecCurveMatches(alg, key)) throw new Error('Curve ' + key.asymmetricKeyDetails.namedCurve + ' does not match ' + alg);

Type guard

function isEsAlgWithMatchingCurve(alg, key) {
  const required = { ES256: 'P-256', ES384: 'P-384', ES512: 'P-521' }[alg];
  return !required || key.asymmetricKeyDetails?.namedCurve === required;
}

Try / catch

try {
  return jwt.sign(payload, ecKey, { algorithm: alg });
} catch (err) {
  if (/requires curve/.test(err.message)) {
    const algByCurve = { 'P-256': 'ES256', 'P-384': 'ES384', 'P-521': 'ES512' };
    return jwt.sign(payload, ecKey, { algorithm: algByCurve[ecKey.asymmetricKeyDetails.namedCurve] });
  }
  throw err;
}

Prevention

When it happens

Trigger: jwt.sign(payload, ecKey, { algorithm: 'ES256' }) where the EC key was generated on the P-384 or secp256k1 curve instead of prime256v1 (P-256).

Common situations: Generating EC keys without specifying namedCurve (some tooling defaults to P-384 or secp256k1); keys exported from cloud KMS or OpenSSL with a curve that doesn't match the chosen algorithm; switching algorithms from ES256 to ES384 without regenerating the key.

Related errors


AI-assisted analysis of auth0/node-jsonwebtoken@b924272f29 (2026-09-02). Data as JSON: /api/errors/83be1cd27b4f6487. Report an issue: GitHub.