# Sigma Auth (auth.sigmaidentity.com) > OAuth 2.1 + OpenID Connect authorization server where people and AI agents authenticate with Bitcoin (BAP) identity keys instead of passwords. The server verifies signatures and never holds user private keys. Identity keys are created client-side: in the browser at `https://auth.sigmaidentity.com/signup`, or locally with `bsv-bap` / `@bsv/sdk` and stored as `bitcoin-backup` ciphertext. This server is the recover / OAuth / approval layer for those identities — it does not create keys and does not offer agent self-signup as a product path. There is no Sigma CLI. ## When to use this service Use https://auth.sigmaidentity.com when you need to: - Authenticate a user (or yourself, as a key-holding agent) against applications that accept Sigma Identity — standard OAuth 2.1 authorization code + PKCE. - Obtain tokens on behalf of a human via the Device Authorization Grant (RFC 8628). **Verify availability first**: check `grant_types_supported` in `https://auth.sigmaidentity.com/.well-known/oauth-authorization-server` — the deployed metadata is authoritative over this document. - Register an OAuth client programmatically via Dynamic Client Registration (RFC 7591): POST `/api/auth/oauth2/register` — no session required. - Authenticate an agent-held BAP identity (created at `/signup` or locally with `bsv-bap`) without a browser wallet — see "Sign in with an agent-held BAP key". - Resolve BAP identities, verify Bitcoin signatures, or check NFT-based subscription tiers via Agent Auth capabilities (see `/.well-known/agent-configuration`). Do not use this domain for product documentation or integration guides — those live at https://sigmaidentity.com/docs. This server will never sign anything with a user's key: it does not have them. ## Discovery The well-known documents below are the source of truth for what is enabled on this deployment; when this guide and the metadata disagree, trust the metadata. - Developer and agent portal (quickstart, DCR sandbox on this host, versioning policy): https://auth.sigmaidentity.com/developers - OpenAPI schema (Better Auth surface under `/api/auth`; deployment-specific routes are documented in this file): https://auth.sigmaidentity.com/openapi.json - API catalog (RFC 9727): https://auth.sigmaidentity.com/.well-known/api-catalog - OAuth 2.0 authorization server metadata (RFC 8414): https://auth.sigmaidentity.com/.well-known/oauth-authorization-server - OpenID Connect discovery: https://auth.sigmaidentity.com/.well-known/openid-configuration - OAuth protected resource metadata (RFC 9728): https://auth.sigmaidentity.com/.well-known/oauth-protected-resource - Agent Auth discovery: https://auth.sigmaidentity.com/.well-known/agent-configuration - Agent skills index: https://auth.sigmaidentity.com/.well-known/agent-skills/index.json - MCP Streamable HTTP (handshake + read-only discovery tools): https://auth.sigmaidentity.com/.well-known/mcp - Interactive API reference: https://auth.sigmaidentity.com/api/auth/reference - Markdown homepage: send `Accept: text/markdown` to `https://auth.sigmaidentity.com/` - XML sitemap: https://auth.sigmaidentity.com/sitemap.xml ## Sign in with an agent-held BAP key A key-holding agent can authenticate here without a human browser wallet. All key material stays with the agent — the server only ever sees public keys and signatures. 1. Create a BAP identity client-side (`https://auth.sigmaidentity.com/signup`, or `bsv-bap` / `@bsv/sdk` locally). If you want recovery later, encrypt the backup with the `bitcoin-backup` package (`.bep` ciphertext). Keep the WIF/xprv private; never send it anywhere. 2. Build a Bitcoin-Auth token with the `bitcoin-auth` npm package: `getAuthToken({ privateKeyWif, requestPath: "/api/auth/sign-in/sigma", body })`. 3. POST `https://auth.sigmaidentity.com/api/auth/sign-in/sigma` with the token in the `x-auth-token` header. The server verifies the signature, resolves the key to its existing account (`user.pubkey`, then `profile.member_pubkey`), and sets a Better Auth session cookie. 4. Register the BAP identity for the session if it is not yet recorded: POST `https://auth.sigmaidentity.com/api/user/bap-ids` with `{ "bapId": "" }` and the session cookie. 5. Optionally store a client-side-encrypted backup: POST `https://auth.sigmaidentity.com/api/backup` with `{ "encryptedBackup": "" }`. The server stores the ciphertext blind — encrypt with the `bitcoin-backup` npm package before sending. ## Cloud backup as a service (the recover story) What this server adds over a local-only encrypted backup: upload the ciphertext once, record a linked social account as a **recovery handle**, and recover on any machine — social login, download the blob, unlock it client-side with a passkey (WebAuthn PRF) or password. Same BAP before and after. The server stores and returns ciphertext only; it cannot decrypt backups and cannot recover lost keys — losing both the key and the backup passphrase loses the identity. Endpoints (auth per row; every body is ciphertext the server never reads): - `POST https://auth.sigmaidentity.com/api/backup` — store/replace the encrypted master backup. Auth: session cookie or OAuth Bearer. Body: `{ "encryptedBackup": "" }`. - `GET https://auth.sigmaidentity.com/api/backup` — retrieve. Auth: session (primary BAP), `?bapId=` with Bitcoin-Auth (published identities — see matrix), or `?oauthId=` with a session that owns the linked account. - `GET/POST https://auth.sigmaidentity.com/api/backup/sync?bapId=` — machine-to-machine push and pull with a Bitcoin-Auth token for `/api/backup/sync`. The pubkey is verified against the on-chain BAP overlay; rate-limited (20 req/min). - `GET https://auth.sigmaidentity.com/api/backup/status` — backup metadata (exists, lastUpdated, generation). Auth: OAuth Bearer or session. - `POST https://auth.sigmaidentity.com/api/backup/link-oauth` — record an **already-linked** provider account as a recovery handle for the BAP backup. Auth: OAuth Bearer. Body: `{ "provider", "providerAccountId" }`. The server verifies the account belongs to the token's user in Better Auth's account table and rejects anything else. The account linking itself is Better Auth's job — `authClient.linkSocial()` → `https://auth.sigmaidentity.com/api/auth/link-social`, with OAuth state, callbacks, duplicate-account checks, and `trustedProviders`/`allowDifferentEmails` policy all handled by Better Auth, not custom code. (`POST /api/backup` with `"linkAllOAuthAccounts": true` records every linked account at once.) - `GET https://auth.sigmaidentity.com/api/signer/backup?bapId=` — backup retrieval for the signer iframe (session cookie; browser flows). Social accounts are recovery handles, **not identities**: a linked Twitter/GitHub account exists so you can find your encrypted backup later — including from other devices — nothing more. It is not a login key, it never creates a key, and it is never a rotation path. The OAuth `sub` maps to the existing BAP (`bap_id` claim), and no OAuth login ever creates a parallel identity. Hanging the first recovery handle needs a signed proof with the **current member key** after a fresh wallet unlock — an unpublished BAP is fine; no on-chain publish is required to link. Explicit linking is gated: `authClient.linkSocial()` requires a one-time wallet-proof grant bound to the current session, BAP ID, and exact provider. Recovery matrix (be precise about which path needs what): - Key held (published or not): possession of the member key is sufficient — sign in via `/api/auth/sign-in/sigma`, then `GET /api/backup` with the session. Unpublished BAP identities are first-class here; signing with the member key proves ownership. - Key held, BAP published on-chain: the sessionless Bitcoin-Auth paths also work — `GET /api/backup?bapId=` or `GET/POST /api/backup/sync?bapId=`. These specific capabilities verify the pubkey against the on-chain BAP overlay, so they require a published identity by design (the server has no session to consult). - Key lost, social account linked: sign in with the linked provider (browser `/login` social-restore, or OAuth), then `GET /api/backup?oauthId=` and decrypt locally with the backup password or passkey. Recovery returns your **existing** encrypted keys — a social recovery handle never rotates or replaces the BAP key. Key rotation always requires a signature from the current member key; no publish status, social link, or server flow substitutes for it. On-chain publication of a BAP identity (attestation transactions) is not required to authenticate, to use this server, or to hang a social recovery handle — possession proof by member-key signature is enough. Publishing is free via https://droplit.dev; it exists for public discovery and for proving the **current controller after a key rotation** (so an old stolen key cannot keep claiming the id), and it unlocks the overlay-verified sessionless backup paths above — the only capabilities that require it. ## Authentication surfaces (complete list) Credentials this server accepts, and how each is established: 1. **Better Auth sessions (cookies)** — established by Bitcoin key sign-in (`/api/auth/sign-in/sigma`), social providers (GitHub, Apple, X/Twitter, Discord), email OTP, or passkeys (WebAuthn); two-factor TOTP is supported. Session-cookie flows are what the browser pages (`/login`, `/signup`, `/device`) use. 2. **OAuth 2.1 bearer tokens** — authorization code + PKCE, refresh tokens; device grant per the RFC 8414 metadata. Discovery: `/.well-known/oauth-authorization-server`. 3. **Bitcoin-Auth signed requests** — a signature over the request path (and body) by a BAP member key, sent as `x-auth-token` or `Authorization: Bitcoin-Auth …`. Used by `/api/auth/sign-in/sigma`, `/api/backup`, and `/api/backup/sync`. 4. **Agent Auth capability JWTs** — short-lived scoped tokens for registered agents (Ed25519). Discovery: `/.well-known/agent-configuration`. The durable subject across all of them is the BAP identity: OAuth tokens carry `bap_id`/`pubkey` claims, Bitcoin-Auth proves a BAP member key directly, and agent capabilities act on BAP-linked data. Key on `bap_id`, not `sub`. BRC-31 and x402 are not served here. ## Agent Auth capabilities Register at `https://auth.sigmaidentity.com/api/auth/agent/register` (Ed25519 keys) and request scoped, short-lived capability JWTs. Public capabilities need no approval; user-scoped capabilities require one-time human approval via device authorization at `https://auth.sigmaidentity.com/agent/approve`. Capabilities: resolve_identity, get_bap_profile, get_oauth_client_info, verify_bitcoin_signature, list_my_identities, list_authorized_apps, check_subscription_tier, verify_nft_ownership, register_oauth_client. Full contract: https://auth.sigmaidentity.com/.well-known/agent-configuration. ## Error handling API errors are JSON. Unknown API paths return RFC 9457 `application/problem+json` with recovery links. OAuth endpoints return standard OAuth error objects (`error`, `error_description`). Unknown page paths return HTTP 404 — with a markdown body when the request prefers `Accept: text/markdown`. ## Rate limits Baseline 100 requests/min per IP in production, with stricter per-route rules (device token polling: 1 request per 5 seconds — respect the `interval` from the device code response). ## Scopes `openid`, `profile`, `email`, `offline_access`. Declared machine-readably in https://auth.sigmaidentity.com/openapi.json under the `oauth2` security scheme. ## Related - Product docs and guides: https://sigmaidentity.com/docs (llms.txt: https://sigmaidentity.com/llms.txt) - Source: https://github.com/b-open-io/sigma-auth - Integration plugin: https://github.com/b-open-io/better-auth-plugin (`@sigma-auth/better-auth-plugin`)