Skip to main content

Integrate BKey as your authorization layer

You do not need our SDK to use BKey. We’re a standards-compliant OAuth 2.1 / OIDC / CIBA (RFC 8958) provider — any auth library that speaks those protocols can talk to BKey directly. Use BKey when you want any of the following in your own app or server:
  • Per-action biometric approval — CIBA: push a consent prompt to a user’s phone, get back a signed JWT proving they approved the specific action.
  • Agent payments — x402 (USDC on Base, via EIP-3009) and MPP (Stripe Shared Payment Tokens). Your 402-serving code calls BKey’s authorize endpoints; BKey handles spending limits, biometric approval, and signing.
  • Standard OAuth 2.1 / OIDCclient_credentials, device_authorization, token exchange, revocation, JWKS.

Discovery

Start here. The discovery document describes every endpoint, grant type, and supported algorithm BKey offers:
Most OIDC libraries auto-configure from this URL. See the OIDC discovery endpoint reference.

Endpoints

Standard OAuth 2.1 / OIDC

Revoke tokens with @bkey/login

The Login with BKey SDK reads the revocation endpoint from OIDC discovery and sends the RFC 7009 request for you:
The SDK sends the correct token type hint and client authentication fields. You do not need to make a separate fetch() call. Revocation applies only to the submitted token. Revoking a refresh token does not revoke related access tokens, so revoke both tokens to end both credentials. The full SDK operation, including discovery, has a five-second deadline and accepts an optional AbortSignal that can cancel it sooner without disabling that deadline.

Per-action biometric approval (CIBA)

Your app calls /oauth/bc-authorize with a login_hint (the user’s DID), a scope, and a human-readable binding_message. The user gets a push notification, approves with biometrics, and your app’s poll returns an EdDSA-signed JWT scoped to that specific action. Typical integration shapes:
  • MCP servers — gate every tool call on CIBA; verify the returned token with @bkey/node or any JWKS-aware JWT library. See MCP integration.
  • Admin consoles / deploy pipelines — require a fresh biometric approval before destructive operations (deploy, rollback, db drop, refund).
  • Any app with a “confirm with your phone” pattern — replace the soft click with a cryptographically bound, replay-resistant attestation.
See the CIBA guide for the full protocol and the one-line SDK pattern.

Agent payments (x402 + MPP)

For agents and 402-serving APIs. BKey handles spending limits, biometric approval (via CIBA above), and payment signing — your agent or server never touches the user’s keys. Auto-detection is built in — the CLI proxy, skill, and SDK inspect the 402 response headers and pick the right protocol. If you’re building a gateway or SDK of your own, you can call these endpoints directly. See the agent payments guide for the auto-detect flow and cost comparison.

Vault (E2EE secrets)

Vault values are end-to-end encrypted between your process and the user’s phone. The server never sees plaintext. See encryption for the full envelope (X25519 ECDH + AES-256-GCM).

Checkout

Registering your app / agent

Before you can hit most of these endpoints, you need a client_id + client_secret:
  • For agents — run bkey auth setup-agent --save from a logged-in CLI. BKey pushes a one-time approval to your phone for the scopes you want, then issues the credentials. Details in CLI authentication.
  • For apps that act as an OIDC client on behalf of other users: use registerClient() from @bkey/login. It registers the app without a dashboard account. For signing users into a website specifically, see Login with bkey.
An anonymous registration returns a registrationAccessToken only once. Store it as a sensitive credential, separate from the OAuth client secret. The registration token manages the client. The client secret only authenticates the client at OAuth endpoints. @bkey/login provides these lifecycle helpers:
  • getRegisteredClient() reads the current metadata.
  • updateRegisteredClient() changes the name and redirect settings.
  • rotateClientSecret() creates a new one-time client secret. Old secrets have a 24-hour grace period by default. Set graceHours: 0 after a leak.
  • deleteRegisteredClient() revokes and deprovisions the client.
  • claimRegisteredClient() assigns an anonymous client to the authenticated user or developer account and revokes its registration access token.
Each helper uses the registrationClientUri returned during registration. Use the one-time registration token as managementAccessToken for an anonymous client. After a claim, use the owner’s user or developer dashboard token. Production can return a management URI on https://api.bkey.id while the issuer is https://id.bkey.id. Use the returned URI without changing its host. The SDK accepts this exact BKey host pair and rejects other cross-origin management URIs. If you retain the management credential, you can change redirect URIs and rotate a lost or leaked client secret without registering a replacement client. BKey does not currently rotate the registration token or client secret during a metadata read or update. The response types still expose replacement values if this behavior changes. Store a returned replacement before the next call.
claimRegisteredClient() does not change an existing management options object. A successful claim revokes the registration access token. Replace managementAccessToken with the owner access token before the next read, update, rotation, or deletion request.

Token format

All tokens BKey issues are JWTs signed with EdDSA (Ed25519):
Access and refresh tokens have aud set to the BKey API (https://api.bkey.id). Only id_tokens set aud to your client_id. Verify with any JWKS-aware JWT library or @bkey/node’s verifyToken(). The library pins alg: EdDSA, enforces scope, and returns null-prototype claims. No HS256 confusion, no alg: none.

Integration patterns

See also