@spfn/signing is the Signer interface and the providers behind it.
The private key may live in this process, in Google Cloud KMS, or in AWS KMS; the caller's
code does not change, and the token on the wire does not change. It signs EdDSA and ES256,
and verifies those two and RS256.
Alpha — the API may move more than the beta packages.
Signing code usually assumes the private key is a string sitting in the
process. That assumption does not survive a cloud KMS, where the key never leaves the service.
createSigner() takes a provider — local, gcp-kms, or
aws-kms — and returns the same Signer either way. EdDSA (Ed25519) is the
default; ES256 stays fully supported for anything downstream that only speaks ECDSA. The KMS SDKs
are optional peer dependencies, installed only for the provider you name.
Verification lives in its own entry point, @spfn/signing/verify,
a single file whose only import is node:crypto — so it can run inside a tenant container
with nothing else shipped beside it. verifyJws() never throws on token input: a malformed
token is a verdict, not an exception. The token's kid selects the key, and that key's
algorithm is the algorithm; the header's alg is only checked for equality with it. That is
what turns algorithm confusion, alg: "none" included, into an alg-mismatch
verdict instead of a decision.
local, gcp-kms and aws-kms behind one Signer; KMS SDKs optional.
@spfn/signing to issue tokens; @spfn/signing/verify, node:crypto only, to check them.
Clock skew, max age, issuer and audience options; a reason on every refusal.
Verify an OIDC issuer's RS256 tokens; parseJwks reads its key set. Fetching it is yours.
definePurposes keeps each token kind's keys and audience out of the others' verifiers.
A KeyRing of public keys, rotated add → switch → wait → remove.
Public keys as a pasteable kid:base64url list — Ed25519, P-256, or SPKI.
Forty committed tokens with the verdict each must produce, for any implementation.