@interop/http-signature-zcap-verify
v12.0.4
Published
A library for invoking Authorization Capabilities via HTTP signatures
Readme
http-signature-zcap-verify (@interop/http-signature-zcap-verify)
A library for verifying Authorization Capability (ZCAP) invocations via HTTP signatures.
It is the verifier counterpart to
@interop/http-signature-zcap-invoke,
which signs the request. On the server, verifyCapabilityInvocation parses the
HTTP signature headers, verifies the signature, dereferences the invoked
capability, and validates the capability delegation chain.
Install
- Browsers, Node.js, and React Native are supported.
- Written in TypeScript; ships ESM with type declarations.
To install from NPM:
pnpm add @interop/http-signature-zcap-verifyUsage
verifyCapabilityInvocation needs two functions you supply:
documentLoader-- a JSON-LD document loader that can resolve the controller document, the invoked root capability, and any contexts in the delegation chain.getVerifier-- an async function that dereferences a key id to a signature verifier and its verification method document.
Setting up the document loader and verifier
import { securityLoader } from '@interop/security-document-loader'
import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'
// Preloaded with the zcap, DID, Multikey, ed25519, and data-integrity contexts.
const documentLoader = securityLoader().build()
async function getVerifier({ keyId, documentLoader }) {
const { document } = await documentLoader(keyId)
// `fromKeyDocument` rebuilds the key from the dereferenced verification
// method and throws if the key has been revoked. It accepts a verification
// method using either the Multikey or the ed25519-2020 suite context.
const key = await Ed25519VerificationKey.fromKeyDocument({ document })
return { verifier: key.verifier(), verificationMethod: document }
}Note: the controller document returned by your
documentLoadershould use the DID v1 context (https://www.w3.org/ns/did/v1) and list the invoking key undercapabilityInvocation. Controllers that use a non-DID context force a framing step against the legacyhttps://w3id.org/security/v2context, which the loader above does not bundle.
Verifying an incoming request
import { verifyCapabilityInvocation } from '@interop/http-signature-zcap-verify'
import { Ed25519Signature2020 } from '@interop/ed25519-signature'
// In an HTTP handler, `req.method`, `req.url`, and `req.headers` come from the
// incoming request. `expectedTarget` is the absolute URL the capability must
// apply to; `expectedRootCapability` is the root zcap ID you authorized.
const result = await verifyCapabilityInvocation({
url: req.url,
method: req.method,
headers: req.headers,
// verify-mode suite for the delegation chain; no signer needed
suite: new Ed25519Signature2020(),
getVerifier,
documentLoader,
expectedHost: 'api.example.com',
expectedAction: 'read',
expectedTarget: 'https://api.example.com/documents/123',
expectedRootCapability:
'urn:zcap:root:' +
encodeURIComponent('https://api.example.com/documents/123')
})
if (!result.verified) {
// `result.error` describes why verification failed (bad signature,
// unexpected host, expired capability, unauthorized key, etc.)
throw result.error
}
// On success, `result` also includes the invoked `capability`,
// `capabilityAction`, the `controller`/`invoker`, the `verificationMethod`,
// and the `dereferencedChain`.
console.log('invoked by', result.controller)Result
verifyCapabilityInvocation resolves to an object and does not throw for
verification failures -- check result.verified:
- On failure:
{ verified: false, error }. - On success:
{ verified: true, capability, capabilityAction, controller, invoker, verificationMethod, dereferencedChain }.
(It does throw a TypeError for programmer errors, such as omitting
getVerifier.)
Key options
| Option | Description |
| -------------------------- | ------------------------------------------------------------------------- |
| url, method, headers | The incoming request. |
| getVerifier | Async function returning { verifier, verificationMethod } for a key id. |
| documentLoader | JSON-LD loader for the controller, root capability, and contexts. |
| expectedHost | The expected Host header (string or array of allowed hosts). |
| expectedAction | The capability action the request must invoke (e.g. 'read'). |
| expectedTarget | The absolute URL the capability must apply to. |
| expectedRootCapability | The authorized root capability ID (string or array). |
| suite | The signature suite(s) used to verify the delegation chain. |
| allowTargetAttenuation | Allow hierarchical RESTful target attenuation (default false). |
| maxClockSkew | Allowed clock skew in seconds (default 300). |
| now | A UNIX timestamp (seconds) or Date to verify against (default: now). |
See the JSDoc on verifyCapabilityInvocation for the full list, including
additionalHeaders, beforeValidatePurpose, inspectCapabilityChain,
maxChainLength, and maxDelegationTtl.
