npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@proof.com/x401-node

v0.2.0

Published

Node.js SDK for the x401 protocol.

Readme

@proof.com/x401-node

Node.js SDK for the x401 protocol (v0.2.0).

x401 gates an HTTP resource behind an identity proof requirement. The server (verifier) returns a PROOF-REQUIRED header carrying a composed Digital Credentials API request; the user agent obtains a presentation for that request and retries with a PROOF-PRESENTATION header. This package implements the data types and processing rules for both the verifier and the user agent.

It does not verify credentials — the presentation result is opaque, so pair it with a credential library such as @proof.com/proof-vc-common. It also does not compose or sign the OpenID4VP request, nor invoke the wallet; the verifier authors the request (out of scope here) and this package carries it opaque in presentation_requirements.

Table of Contents

Installation

npm install @proof.com/x401-node

Verifier

Protect a resource (PROOF-REQUIRED)

The x401 payload carries the Verifier-composed Digital Credentials request and the OAuth token endpoint used for token exchange. You compose and (for the RECOMMENDED signed mode) sign the OpenID4VP request yourself; this package carries it opaque.

import { verifier } from "@proof.com/x401-node";

const payload = verifier.buildPayload({
  presentationRequirements: {
    requests: [
      {
        protocol: "openid4vp-v1-signed",
        data: { request: signedOpenId4vpRequestJwt },
      },
    ],
  },
  oauth: { token_endpoint: "https://research.example.com/oauth/token" },
  trustEstablishment:
    "https://research.example.com/.well-known/x401/trust/basic-v1",
  requestId: "proof-template-basic-v1",
  satisfiedRequirements: ["urn:proof:x401:satisfaction:basic:v1"],
});

protocol is openid4vp-v1-signed (RECOMMENDED) or openid4vp-v1-unsigned, and its data carries the request you composed and signed. trustEstablishment, requestId, and satisfiedRequirements are optional hints.

Return it as a header:

response.setHeader("PROOF-REQUIRED", verifier.encodePayload(payload));

For clients that read the body but not the headers, mirror the requirement as an embedded <data> element (the $schema marker is added automatically). The header remains authoritative and must still be set.

const html = `<article>…</article>${verifier.embedHtmlData(payload)}`;

Verify a Proof (PROOF-PRESENTATION)

Decode the artifact, then validate the presentation against the request you composed (binding, nonce freshness, credential query) with your credential library and route policy. The artifact may carry the result inline (response) or by reference (presentation_uri, which you dereference). On failure, return an x401 Error Object in PROOF-RESPONSE. See the full verifier processing rules.

const artifact = verifier.decodeVPArtifact(
  request.headers["proof-presentation"],
);

const result = artifact.response
  ? artifact.response
  : await fetchPresentation(artifact.presentation_uri!);

if (!validatePresentation(result)) {
  response.setHeader(
    "PROOF-RESPONSE",
    verifier.encodeErrorObject(
      verifier.buildErrorObject({ error: "invalid_presentation" }),
    ),
  );
  return;
}

Agent

See the full agent processing rules.

Read a Proof requirement (PROOF-REQUIRED)

detectProofRequirement reads the header, falling back to the embedded <data> element. getDigitalCredentialRequest returns the Verifier-composed request unmodified — pass it straight to the Digital Credentials API (or relay it). The agent MUST NOT alter it.

import { agent } from "@proof.com/x401-node";

const res = await fetch(url);
const requirement = agent.detectProofRequirement({
  headers: res.headers,
  body: await res.text(),
});

if (requirement) {
  const dcRequest = agent.getDigitalCredentialRequest(requirement.payload);
  const result = await navigator.credentials.get({ digital: dcRequest });
}

If you're an intermediary relaying the request to a remote handler (which POSTs the result back rather than invoking the DC API itself), add an https return_uri to the forwarded payload with agent.addReturnUri(payload, returnUri). Only a relaying intermediary sets this — never the Verifier.

Present a Proof (PROOF-PRESENTATION)

Wrap the { protocol, data } presentation result in a VP Artifact and retry the same route. Use the by-reference form for results too large for a header.

const artifact = agent.buildVPArtifact({
  response: result,
  requestId: requirement.payload.request_id,
});

await fetch(url, {
  headers: { "PROOF-PRESENTATION": agent.encodeVPArtifact(artifact) },
});

Or, by reference:

const artifact = agent.buildVPArtifactReference({
  presentationUri:
    "https://research.example.com/.well-known/x401/presentations/abc",
  expiresAt: "2026-05-06T18:50:00Z",
});

Exchange a Proof for a token

Exchange the artifact for a reusable Verification Token via OAuth token exchange, then present it as an x401 Token Object.

const form = agent.buildTokenExchangeForm(artifact, { resource: url });
const res = await fetch(tokenEndpoint, {
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: form,
});
const { access_token } = agent.parseTokenExchangeResponse(await res.json());

const tokenHeader = agent.encodeTokenObject(
  agent.buildTokenObject(access_token),
);
await fetch(url, { headers: { "PROOF-PRESENTATION": tokenHeader } });

Contributing

Contribution guidelines for this project