Applications And OAuth¶
Applications use SigID through OAuth 2.1 and OpenID Connect. SigID hosts the authentication experience, records consent, and returns tenant-scoped tokens to your application.
Recommended flow¶
Use Authorization Code with PKCE for browser, native, and desktop applications.
- Your application creates a high-entropy
state,code_verifier, andcode_challenge. - The browser redirects to
/oauth/authorize. - SigID authenticates the user and applies tenant policy.
- SigID prompts for consent when scopes or profile claims are new.
- SigID redirects to your registered callback with an authorization code.
- Your backend exchanges the code at
/oauth/token. - Your backend validates tokens and establishes an application session.
GET /oauth/authorize
?response_type=code
&client_id=CLIENT_ID
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20profile%20email
&code_challenge=BASE64URL_SHA256_VERIFIER
&code_challenge_method=S256
&state=OPAQUE_CSRF_VALUE
Do not skip backend validation
Frontend login state is not authorization. Your API must validate the access token on every protected request or through a trusted session that was created after token validation.
OAuth and OIDC endpoints¶
| Endpoint | Use |
|---|---|
/.well-known/openid-configuration |
Discover issuer, authorization endpoint, token endpoint, JWKS, UserInfo, revocation, and introspection metadata |
/.well-known/jwks.json |
Fetch public keys for token signature validation |
/oauth/authorize |
Start hosted login and consent |
/oauth/par |
Store a pushed authorization request and receive a request_uri |
/oauth/token |
Exchange authorization codes, refresh tokens, client credentials, token exchange, device code, or CIBA polling requests |
/oauth/revoke |
Revoke supported token types |
/oauth/introspect |
Check token status from a trusted backend |
/oauth/device/code |
Start device authorization for CLI and input-constrained clients |
/oauth/device/verify |
User-facing device verification page |
/bc-authorize |
Start OIDC CIBA backchannel authentication |
/oauth/end-session |
OIDC RP-initiated logout |
/oauth/register |
Dynamic client registration when enabled |
/userinfo |
Return consented OIDC profile claims |
Dynamic Client Registration can be used by @sigid/init to create development
applications from a terminal or coding agent. On shared issuer hosts, explicit
tenant selection with tenant_id or tenant_slug is accepted only when DCR is
protected by an initial access token.
Grant types¶
| Grant type | Use it for | Avoid when |
|---|---|---|
authorization_code with PKCE |
Human login for web, mobile, desktop, and server-rendered apps | Machine-only service access |
client_credentials |
Service clients and automation acting as themselves | User login or delegated user actions |
refresh_token |
Renewing sessions without another browser redirect | High-risk actions that need step-up |
urn:ietf:params:oauth:grant-type:token-exchange |
Reduced delegated access for agents, services, or vault grants | Broad impersonation |
urn:ietf:params:oauth:grant-type:device_code |
CLI, TV, device, or terminal flows | Normal browser applications |
urn:openid:params:grant-type:ciba |
Backchannel authentication where the client cannot redirect the user | Normal browser applications |
Token validation¶
When your API receives an access token, validate:
| Check | Why it matters |
|---|---|
| Issuer | Prevents accepting tokens from another authority |
| Audience | Ensures the token was minted for your API |
| Signature | Confirms the token was issued by SigID |
| Expiration and not-before | Rejects stale or future tokens |
| Tenant context | Prevents cross-tenant access |
| Scopes | Enforces API permission |
| Subject type | Distinguishes human, agent, and service behavior |
| DPoP binding, when used | Confirms the caller possesses the bound key |
Minimal backend authorization pattern:
1. Parse bearer token.
2. Resolve issuer metadata and JWKS.
3. Verify signature and claims.
4. Load tenant and subject from validated claims.
5. Check required scope for the requested API operation.
6. Check subject type (human, agent, service, or delegated).
7. Apply organization, role, policy, or delegation rules.
8. Record high-impact actions in audit logs.
9. Serve the request or return an authorization error.
Tenant-scoped subjects¶
Tenant applications receive tenant-local subjects and tenant-scoped authority.
Do not assume a user's sub is the same across tenants. Use the tenant-local
subject as the durable user key inside your application.
Use global identifiers only when a documented product workflow explicitly shares them. Pairwise subject identifiers are designed to reduce cross-tenant correlation.
Scopes and consent¶
Request only the scopes your application needs for the current workflow. If you later request broader access, SigID prompts the user again.
| Prompt parameter | Result |
|---|---|
prompt=login |
Require the user to sign in again |
prompt=consent |
Require a fresh consent decision |
prompt=none |
Attempt silent login and fail if interaction is needed |
max_age |
Require authentication within a recent time window |
Consent should be understandable without reading your source code. Scope names can be technical; consent descriptions should explain the outcome.
Advanced authorization requests¶
Use Pushed Authorization Requests for high-value integrations or clients that
need FAPI-style request integrity. POST the same authorization parameters to
/oauth/par, then redirect the browser to /oauth/authorize with the returned
request_uri.
The authorization endpoint accepts Rich Authorization Requests through the
authorization_details parameter and OIDC individual claim requests through the
claims parameter. Authorization codes retain those request details through
token issuance so APIs can enforce fine-grained consent.
Use acr_values when a route needs a minimum authentication assurance level.
If the current session is below the requested ACR, SigID returns a step-up
requirement instead of issuing an authorization code.
For CIBA, POST /bc-authorize to create a backchannel request, then poll
/oauth/token with grant_type=urn:openid:params:grant-type:ciba and the
returned auth_req_id until the request is approved, denied, expired, or still
pending.
Refresh tokens and revocation¶
Use refresh tokens when your application needs long-lived sessions. Protect them like credentials:
- store refresh tokens server-side or in platform-secure storage
- rotate tokens according to the token response behavior
- revoke refresh tokens on logout, account compromise, or device loss
- treat reuse detection as a security event
- keep access tokens short-lived
Use /oauth/revoke when a user disconnects an application, an administrator
suspends access, or an incident requires token invalidation.
Device authorization¶
Device Authorization is designed for clients that cannot receive browser redirects, such as CLIs or devices with limited input.
- The client requests a device code at
/oauth/device/code. - SigID returns a user code, verification URI, device code, and polling interval.
- The user opens the verification URI and approves or denies the request.
- The device polls
/oauth/tokenwith the device-code grant until completion, denial, expiry, orslow_down.
Respect the returned polling interval. Treat authorization_pending as normal,
slow_down as a signal to back off, and expired_token as a reason to restart
the flow.
Hosted sign-in methods¶
Tenant administrators can enable email and password, passkeys, magic links, OTP, social OAuth, enterprise SSO, SIWE wallet authentication, and anonymous accounts. For all supported methods and descriptions, see Product Reference.
Use step-up MFA or fresh login for sensitive actions such as billing changes, organization ownership transfer, credential export, wallet signing, or administrator access.
Common integration mistakes¶
| Mistake | Correct approach |
|---|---|
| Using email as the primary user key | Use the tenant-local subject |
| Accepting tokens without checking audience | Configure and validate the API audience |
| Trusting frontend-only login state | Validate access tokens in the backend |
| Reusing one OAuth client everywhere | Create clients per application or runtime boundary |
| Requesting broad scopes at first login | Request scopes when the user reaches the feature that needs them |
Ignoring state |
Validate state to prevent CSRF and callback confusion |
| Treating agents as users | Check subject type and delegation claims |