Skip to main content

Identity (OIDC)

The fleet identity provider — one OIDC issuer for all products, so a single account authenticates across the fleet (the cross-product SSO the census found impossible). Signs RS256/JWKS; per-brand realms. Consolidates the 19-service platform auth + voice + bellring (C3). The signing key is resolved server-side and NEVER present in a repo, a consumer, or a facade. Status: OIDC provider LIVE (discovery+JWKS+authorize+token+userinfo+introspect+revoke+register+ session/end served by node-oidc-provider) + strong-auth surface (MFA/WebAuthn/lockout/enterprise-SSO) ABSORBED from vagary-platform (Track S core-merge, additive). Consolidation remains the staged C3 build: Phase 1 ETL → G0 gate → Phase 2 repoint-with-fallback → Phase 3 per-consumer deletes (voice last).

  • Group: Auth & gateway
  • Contract: contracts/identity/v1/openapi.yaml
  • Public access: none — internal-only capability. It is NOT exposed on the public API gateway (https://api.vagarylabs.com); it is reachable only inside the fleet (container/tailnet) by first-party callers. There is no customer-facing endpoint to call.

Endpoints

MethodPathSummary
GET/.well-known/openid-configurationOIDC discovery document (GROUNDED — live in scaffold)
GET/jwksJSON Web Key Set — public keys for RS256 verification (GROUNDED — live in scaffold)
POST/tokenOAuth2/OIDC token endpoint (GROUNDED — real grant handling via node-oidc-provider)
GET/healthliveness
GET/metricsPrometheus text exposition
POST/provision/usersProvision a product end-user (internal signup delegation — identity is the SOLE cred store)
POST/provision/passwordChange a product end-user's password (internal delegation)
POST/password-reset/requestBegin a self-service password reset
POST/password-reset/confirmRedeem a reset token and set a new password
POST/provision/erase-subjectGDPR Art-17 SUBJECT-scoped erasure — forget a person across all 25 identity tables
GET/authorizeOAuth2/OIDC authorization endpoint (authorization_code + PKCE) — GROUNDED
GET/userinfoOIDC UserInfo (bearer access token) — GROUNDED
POST/introspectRFC 7662 token introspection (client-authenticated) — GROUNDED
POST/revokeRFC 7009 token revocation (client-authenticated) — GROUNDED
POST/registerOIDC dynamic client registration — GROUNDED
GET/session/endOIDC RP-initiated logout (end_session) — GROUNDED
POST/account/mfa/enablebegin TOTP MFA enrollment (returns secret + backup codes ONCE)
POST/account/mfa/activateverify the first TOTP code and activate MFA
POST/account/mfa/verifyverify a TOTP or a one-time backup code
POST/account/mfa/disabledisable MFA for a user
GET/account/mfa/statusMFA status for a user
POST/account/webauthn/register-beginbegin WebAuthn passkey registration (issue challenge)
POST/account/webauthn/register-completecomplete WebAuthn passkey registration
POST/account/webauthn/authenticate-beginbegin WebAuthn assertion (issue challenge)
POST/account/webauthn/authenticate-completecomplete WebAuthn assertion (sign-count anti-clone enforced)
GET/account/webauthn/credentialslist a user's registered passkeys
POST/account/webauthn/credentials-removeremove a user's passkey
POST/account/sso/providersregister an upstream SSO provider (saml
GET/account/sso/providerslist registered SSO providers
POST/account/sso/initiateinitiate SSO login (SAML redirect / OIDC authorization URL)
POST/account/sso/callbackhandle an SSO callback (SAML response / OIDC code)
POST/account/sso/linklink an upstream SSO identity to a local user
GET/account/sso/linkslist a user's SSO links
POST/account/sso/unlinkremove an SSO link
POST/account/sessions/createcreate a tracked device session
GET/account/sessionslist a user's active sessions
POST/account/sessions/revokerevoke a single session
POST/account/sessions/revoke-allrevoke all sessions (optionally all-except keep_session_id)
POST/account/security/revoke-user-tokensblanket-revoke ALL of a user's tokens (logout-all / compromised account)
POST/account/security/revoke-jtideny a specific token by its jti for a ttl
GET/account/security/token-statuscheck per-user blanket + per-jti revocation status (for consumers enforcing revocation)
GET/account/security/revocationsincremental revocation delta since a monotonic cursor (JTI denylist + user-blanket entries)
POST/account/social/authorizebuild a social-provider authorization URL (+ CSRF state carrying realm/org context)
POST/account/social/callbackhandle a social callback (code-exchange, profile fetch, find-or-create + link)
GET/account/social/linkslist a user's linked social providers
POST/account/social/unlinkunlink a social provider from a user
POST/account/api-keysissue an org-scoped api-key for a user (returns the raw key ONCE)
GET/account/api-keyslist an org's api-keys (redacted — no hash); optional user_id narrows to one user
POST/account/api-keys/verifyverify a raw api-key (raw key in the body — never a URL); returns org/user/scope context
PATCH/account/api-keys/{keyId}update an org's api-key name and/or scopes (folds platform update_key)
DELETE/account/api-keys/{keyId}revoke an org's api-key by its external handle

Schemas

Jwks

FieldTypeDescription
keysarray

ProvisionUserRequest

FieldTypeDescription
realmstringper-brand realm the user belongs to
emailstring
passwordstring
organization_idstringproduct-tier end-customer tenant (I6 — never Paperclip companyId)
name['string', 'null']
rolesarray

ProvisionedUser

FieldTypeDescription
idstring
emailstring
realmstring
organization_idstring

PasswordResetRequest

FieldTypeDescription
realmstring
emailstring

PasswordResetConfirm

FieldTypeDescription
tokenstringthe raw reset token from the emailed link; never logged or stored
passwordstringthe new password

Accepted

FieldTypeDescription
statusstring

ProvisionPasswordRequest

FieldTypeDescription
realmstring
idstringsubject (user id / sub)
passwordstring

PasswordUpdated

FieldTypeDescription
updatedboolean

Generated by scripts/gen-capability-docs.py from contracts/identity/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page.