---
summary: Triage SigID login, OAuth, token validation, SSO, SCIM, webhook, agent, session, wallet, and operational issues.
tags:
  - troubleshooting
  - oauth
  - sso
  - webhooks
  - token validation
categories:
  - Reference
  - Operations
---

# Troubleshooting

<!-- agent:page
You are an AI agent using this reference to triage SigID integration and tenant operation failures.
- Start at the Quick Triage table and follow the section that matches the symptom; do not jump to fixes before matching it.
- Map error codes against the common error code table exactly (`invalid_grant`, `unauthorized_client`, `invalid_dpop_proof`, `use_dpop_nonce`, and the rest); each implies a different starting point.
- Never bypass token validation, webhook signature checks, DPoP proof checks, or tenant authorization while debugging; fail closed.
- Collect the safe evidence list first (`x-request-id`, tenant, client ID, exact redirect URI, sanitized error JSON); never collect raw tokens, secrets, MFA codes, or unnecessary PII.
- Sections covering SCIM, DPoP, wallet, vault, billing, agent identity, and MCP apply only when the feature is enabled in the target deployment and tenant.
- For deeper procedures, follow the per-section links (Verify Tokens, Webhooks, Agent And MCP Auth, OAuth And OIDC).
-->

Use this guide to triage common SigID integration and tenant operation issues.
Start with the symptom, collect safe evidence, then follow the section for that
problem area.

Do not bypass token validation, webhook signature checks, DPoP proof checks, or
tenant authorization checks while debugging. Fail closed and use a trusted
backend fallback such as introspection only when the relevant guide says it is
safe.

Some sections cover optional capabilities such as SCIM, DPoP, wallet, vault,
billing, agent identity, and MCP. Use those sections only when the feature is
enabled in the target deployment and tenant.

## Quick Triage

| Symptom | Start with |
|---|---|
| Login fails before consent | [Login And Sign-In Issues](#login-and-sign-in-issues) |
| OAuth callback includes an error | [Callback And Token Exchange Issues](#callback-and-token-exchange-issues) |
| `/oauth/token` returns an OAuth error | [Callback And Token Exchange Issues](#callback-and-token-exchange-issues) |
| API returns `401` or `403` | [Token Validation Issues](#token-validation-issues) or [Access And Authorization Issues](#access-and-authorization-issues) |
| `/userinfo` is missing profile fields | [UserInfo And OIDC Claims](#userinfo-and-oidc-claims) |
| SSO loops or does not start | [Enterprise SSO And Organizations](#enterprise-sso-and-organizations) |
| SCIM user state is wrong | [Organizations And SCIM](#organizations-and-scim) |
| Webhook delivery fails | [Webhook And Event Issues](#webhook-and-event-issues) |
| Agent or MCP access is denied | [Agent And Delegation Issues](#agent-and-delegation-issues) |
| Session disappears or device state looks wrong | [Session And Device Issues](#session-and-device-issues) |
| Wallet signing or vault access is denied | [Wallet And Vault Issues](#wallet-and-vault-issues) |
| Request is rate-limited or feature is disabled | [Billing, Feature Availability, And Rate Limiting](#billing-feature-availability-and-rate-limiting) |

## How SigID Errors Are Returned

Most SigID API errors use RFC 7807 Problem Details fields plus OAuth-compatible
fields:

```json
{
  "type": "https://sigid.org/errors/invalid-grant",
  "title": "Bad Request",
  "status": 400,
  "detail": "authorization code is invalid or expired",
  "error": "invalid_grant",
  "error_description": "authorization code is invalid or expired"
}
```

Some OAuth and bearer-token middleware responses may only include OAuth-style
fields such as `error` and `error_description`. For debugging, record the HTTP
status, `error`, `error_description`, and `x-request-id` response header.

Common error codes:

| Error | Usually means | Start with |
|---|---|---|
| `invalid_grant` | Authorization code, refresh token, device code, CIBA request, or delegation token is invalid, expired, reused, or mismatched | Callback and token exchange |
| `unsupported_grant_type` | The literal `grant_type` value is malformed or unsupported | Token request format |
| `invalid_client` | Client authentication failed or client ID is wrong for the tenant | Application client settings |
| `invalid_redirect_uri` | Redirect URI is not registered or does not match exactly | Application redirect URIs |
| `pkce_required` | Public client request is missing PKCE | Authorization request |
| `invalid_scope` | Requested scope is malformed or not allowed | Scope configuration |
| `insufficient_scope` | Token is valid but lacks the required scope | API authorization |
| `consent_required` | User or tenant policy requires consent before access | Hosted auth and consent |
| `token_expired` | Access token is expired | Token refresh or re-authentication |
| `token_revoked` | Token or session was revoked | Session, logout, or incident handling |
| `invalid_dpop_proof` | DPoP proof is missing, malformed, or does not bind to the token/request | DPoP validation |
| `use_dpop_nonce` | Retry with the nonce returned by SigID | DPoP token request |
| `delegation_expired` | Delegation grant is no longer active | Delegation |
| `wallet_frozen` | Wallet signing is blocked by freeze state | Wallet operations |
| `budget_exceeded` | Wallet or delegation spend controls rejected the action | Wallet budgets |
| `recipient_not_allowed` | Recipient allowlist rejected the transaction | Wallet policies |
| `billing_feature_disabled` | Feature is not available for the current plan or deployment | Billing and feature availability |
| `rate_limited` | Request frequency or quota exceeded | Rate limiting |

## What To Collect Before Debugging

<!-- agent:action Collect safe debugging evidence
Gather every applicable item from the list before debugging or escalating: tenant, environment, `x-request-id`, client ID, exact redirect URI, tenant-local subject, sanitized headers and error JSON, timestamps, audit entries, and relevant logs.
- redact secrets from everything you collect
- never include raw access, refresh, or ID tokens, webhook secrets, client secrets, SCIM tokens, API keys, MFA or recovery codes, or unnecessary PII
- record the timestamp with timezone so audit logs can be correlated
-->

Collect:

- tenant slug or ID
- environment name, such as development, staging, or production
- `x-request-id`
- application client ID
- exact redirect URI
- user tenant-local subject, when available
- organization ID or slug, when relevant
- agent ID and key fingerprint, when relevant
- webhook delivery ID and event type, when relevant
- sanitized request and response headers
- sanitized error JSON
- timestamp with timezone
- audit log entries around the failure
- browser console errors for frontend issues
- application logs around the failure, with secrets redacted

Do not collect raw access tokens, refresh tokens, ID tokens, webhook secrets,
client secrets, SCIM tokens, API keys, MFA codes, recovery codes, or unnecessary
PII in support tickets.

## Login And Sign-In Issues

Check:

- `client_id` belongs to the expected tenant application
- `redirect_uri` exactly matches a registered redirect URI, including scheme,
  host, path, port, and trailing slash
- `response_type=code`
- `code_challenge_method=S256`
- `scope` contains `openid` when OIDC claims are expected
- tenant login methods are enabled
- email, phone, social, SIWE, or SSO providers are configured where needed
- user is not suspended or removed in the tenant
- SSO enforcement is not routing the user to a misconfigured provider
- request is not being rate-limited

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Invalid redirect URI | URI mismatch, trailing slash difference, wrong environment, or wrong scheme/port |
| Missing login option | Sign-in method disabled for tenant, organization, or deployment |
| SSO starts unexpectedly | Verified-domain routing or organization policy is enforcing SSO |
| SSO does not start | Domain is not verified or the email is outside the routed domain |
| Silent login fails | `prompt=none` requires an existing session and no interaction |
| `429 Too Many Requests` | Login, OTP, or verification endpoint is rate-limited |

## Callback And Token Exchange Issues

<!-- agent:action Diagnose token exchange failures
Work through the checklist against the failing request, then match the error code in the symptom table.
- `invalid_grant`: code reused, expired, wrong `redirect_uri`, wrong `code_verifier`, or wrong tenant/client context
- `invalid_client` vs `unauthorized_client`: client authentication mismatch vs grant type not allowed on the application
- confirm `application/x-www-form-urlencoded`, the exact `grant_type` literal, and a DPoP proof when required (`use_dpop_nonce` means retry with the returned nonce)
- treat callback errors as user-visible retry states; log request ID and error code, never tokens
-->

Check:

- `state` matches the value your app created
- authorization code is exchanged only once
- token exchange uses the same `redirect_uri`
- backend uses the original `code_verifier`
- `code_verifier` matches the original `code_challenge`
- client authentication method matches the application type
- confidential clients do not expose secrets in frontend code
- token endpoint request uses `application/x-www-form-urlencoded`
- `grant_type` is the exact value for the intended flow
- DPoP proof is present when the client or token requires it
- token endpoint request is not being rate-limited

Treat callback errors as user-visible states. Show a retry path and log the
request ID, tenant, client ID, and error code without logging tokens.

Common symptoms:

| Symptom | Likely cause |
|---|---|
| `invalid_grant` on code exchange | Code reused, expired, wrong `redirect_uri`, wrong `code_verifier`, or wrong tenant/client context |
| `unsupported_grant_type` | Literal `grant_type` is wrong or malformed |
| `invalid_client` | Client secret, auth method, or client ID does not match application configuration |
| `unauthorized_client` | Application is not allowed to use the requested grant type |
| `invalid_dpop_proof` | Missing, malformed, expired, or mismatched DPoP proof |
| `use_dpop_nonce` | Retry the request with the returned `DPoP-Nonce` value |

## Token Validation Issues

<!-- agent:action Diagnose token validation failures
Walk the checklist in order: issuer vs discovery, audience vs your API, JWKS freshness, expiry and clock sync, token type, scope, tenant match, `subject_type`, `act`, and DPoP `cnf.jkt`.
- signature failures usually mean a stale JWKS cache, wrong issuer, or wrong environment
- a valid token with `403` points at missing scope, wrong subject type, policy denial, or organization context mismatch
- never accept a DPoP-bound token as plain Bearer; check `cnf.jkt` and the proof
- use introspection only from a trusted backend, and keep the API failing closed
-->

Check:

- issuer matches discovery metadata
- audience matches your API
- JWKS cache is current
- token has not expired
- server clock is synchronized
- token is an access token, not a refresh token or ID token used as API auth
- required scope is present
- tenant in token matches requested tenant resource
- `subject_type` is allowed for the route
- delegated tokens include expected `act` claims
- DPoP proof is present and valid when `cnf.jkt` is present
- your API fails closed when validation metadata is unavailable

Use introspection only from a trusted backend when local JWT validation is not
enough or when you need current server-side token state.

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Token signature fails | JWKS cache is stale, wrong issuer, or wrong environment |
| Audience mismatch | Token was minted for another API or client |
| Valid token but API returns `403` | Missing scope, wrong subject type, policy denial, or organization context mismatch |
| DPoP-bound token accepted as Bearer | Resource server is not checking `cnf.jkt` and DPoP proof |
| Intermittent expiration failures | Server clock drift or long-running request using near-expired token |

See [Verify Tokens](../developers/verify-tokens.md) for the full backend validation
contract.

## Access And Authorization Issues

Check:

- tenant user status is active
- organization membership is present when required
- active organization context matches the requested resource
- role assignment includes the needed permissions
- application requested the needed scopes
- backend checks tenant-local subject, not email
- policy does not require MFA, fresh login, or another step-up
- suspended or removed membership has not been cached by your app
- cached authorization state has been refreshed after role or policy changes

Common symptoms:

| Symptom | Likely cause |
|---|---|
| User can sign in but cannot access app | Tenant membership is pending, suspended, removed, or missing |
| User has no roles | Role assignment missing, organization membership missing, or stale cache |
| `insufficient_scope` | App did not request the required scope or token was minted before scope change |
| `policy_denied` | Conditional access policy rejected the request |
| User sees wrong organization data | Active organization context or tenant isolation check is wrong |

## UserInfo And OIDC Claims

Check:

- access token is valid before calling `/userinfo`
- requested scopes include the claims you expect, such as `profile`, `email`,
  or `phone`
- user granted consent for those claims
- user actually has those profile values
- app does not use `/userinfo` as an authorization oracle

`openid` identifies an OIDC request, but it does not guarantee profile, email,
or phone fields. Use access-token validation, scopes, tenant context, subject
type, organization context, and policies for authorization.

Common symptoms:

| Symptom | Likely cause |
|---|---|
| `/userinfo` returns only `sub` | Missing profile/email/phone scopes or consent |
| Email is missing | `email` scope was not granted or user has no email claim |
| Profile values differ from app cache | App cached old claims or user updated profile data |
| API access denied even though `/userinfo` works | `/userinfo` is profile data, not API authorization |

## Enterprise SSO And Organizations

Check:

- organization domain is verified
- `POST /auth/check-sso` returns the expected routing result for a non-admin
  test user
- provider issuer, authorization endpoint, token endpoint, UserInfo endpoint,
  and JWKS URI are correct
- provider client ID and secret are current
- SigID redirect URI is registered with the provider
- provider is returning required claims
- group or role mapping still matches provider output
- organization membership and role are correct
- a break-glass administrator remains available

Roll out enforcement gradually and monitor failed SSO events.

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Redirect loop between SigID and IdP | Redirect URI, issuer, state cookie, or provider settings mismatch |
| User not routed to SSO | Domain not verified, email outside verified domain, or routing policy not enforced |
| SSO token validation fails | IdP issuer, client ID, JWKS URI, or clock skew |
| User signs in but lacks organization access | Membership, role mapping, or active organization context is missing |
| Admin locked out | SSO enforcement was enabled without a break-glass path |

## Organizations And SCIM

Check:

- SCIM token is current and stored securely
- directory provider targets the correct tenant and base URL
- SCIM user IDs map to the expected tenant users
- `active: false` semantics match your deprovisioning policy
- DELETE behavior matches your tenant removal policy
- role or group mapping is still aligned with IdP claims
- application cache refreshes after directory updates
- organization domains and membership roles are current

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Directory says user is disabled but app still allows access | Application cached authorization state or sessions were not refreshed |
| User removed from directory but still has organization role | SCIM mapping or deprovisioning flow did not remove the membership/role |
| Duplicate membership | External ID or email mapping changed in the directory |
| SCIM calls return unauthorized | SCIM token revoked, wrong tenant, or wrong environment |

## Agent And Delegation Issues

Check:

- agent is active
- anchor is verified and not revoked
- signing key is active
- key rotation completed and runtime uses the new key
- requested scope is allowed for the agent
- delegation exists and has not expired
- delegation chain depth allows the requested delegation level
- user consent covers the requested action
- MCP server audience matches the token
- actor token is valid and has the expected subject type
- DPoP proof is present when the actor token is sender-constrained
- policy does not require human approval or MFA step-up

For incidents, suspend the agent and revoke delegations before investigating
downstream side effects.

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Agent authentication fails | Key invalid, key revoked, challenge expired, unsupported algorithm, or agent suspended |
| Token exchange returns `invalid_grant` | Subject token, actor token, tenant context, delegation, or chain state is invalid |
| Token exchange returns `delegation_expired` | Delegation grant is past `expires_at` |
| Token exchange returns `invalid_dpop_proof` | Actor token requires a matching DPoP proof |
| Agent can authenticate but cannot call tool | Audience, scope, policy, or MCP protected resource metadata mismatch |

## Webhook And Event Issues

<!-- agent:action Diagnose webhook delivery failures
Check the subscription first (active, event type selected, HTTPS URL reachable), then audit the receiver against the mistake table.
- signature mismatch: receiver re-serialized the body, used the wrong secret, or built the canonical string wrong; verify the raw body with constant-time comparison
- duplicate side effects: receiver is not deduplicating `X-SigID-Delivery` before processing
- repeated retries: receiver returns non-2xx, times out, or fails before persistence; return 2xx only after durable acceptance
- reject deliveries where now minus `X-SigID-Timestamp` exceeds `X-SigID-Signature-Max-Age`, and reject unknown signature suites
-->

Check:

- subscription is active
- event type is selected
- receiver URL is HTTPS and reachable
- receiver returns `2xx` only after safely accepting the event
- receiver verifies signatures against the raw request body using the full
  canonical string format
- receiver checks timestamp, max age, delivery ID, event type, suite, and
  signature headers
- receiver allows the SigID request timeout
- duplicate delivery IDs are handled idempotently
- receiver logs delivery IDs without logging secrets or full sensitive payloads

For the full list of delivery headers and signature verification steps, see
[Webhooks](../developers/webhooks.md).

Common receiver mistakes:

| Mistake | Fix |
|---|---|
| Re-serializing JSON before verification | Verify the raw body |
| Comparing signatures with normal string equality | Use constant-time comparison |
| Processing before deduplication | Store delivery ID first |
| Returning `2xx` before persistence | Return success only after safe acceptance |
| Logging full payloads | Redact sensitive fields |
| Ignoring the timestamp or max-age | Reject deliveries where `now - timestamp` exceeds `X-SigID-Signature-Max-Age` |
| Not checking the suite header | Reject if `X-SigID-Signature-Suite` is missing or unrecognized |

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Signature mismatch | Raw body changed, wrong secret, wrong canonical string, or timestamp/suite handling is wrong |
| Duplicate side effects | Receiver does not deduplicate `X-SigID-Delivery` |
| Delivery retries repeatedly | Receiver returns non-`2xx`, times out, or fails before persistence |
| Event not received | Event type not selected, subscription inactive, URL unreachable, or feature/plan limit blocks delivery |

## Session And Device Issues

Check:

- session cookie is sent on the relevant requests
- cookie domain, path, `Secure`, and `SameSite` settings fit your deployment
- browser is not blocking the cookie path your app relies on
- user did not sign out or revoke the session
- session has not expired
- known device or trusted-device state has not been removed or expired
- active organization or account-switcher context is the one your app expects

Common symptoms:

| Symptom | Likely cause |
|---|---|
| Session lost after redirect | Cookie domain/path, secure context, or browser cookie policy issue |
| Trusted device not recognized | Trusted-device cookie expired, cleared, or revoked |
| User switched account unexpectedly | Account switcher state or session stack is not what the app expects |
| Organization context missing | User has not selected an active organization or app cache is stale |

## Wallet And Vault Issues

Check:

- wallet is provisioned for the subject and chain
- wallet is not frozen
- wallet budget allows the transaction
- delegation spend limits allow the transaction
- recipient and contract allowlists include the target
- signing backend is available for the deployment
- token subject and actor are allowed to use the wallet
- vault credential exists and grant is active
- delegated token has the scope required for vault or wallet access

Common symptoms:

| Symptom | Likely cause |
|---|---|
| `wallet_not_provisioned` | Wallet does not exist for the requested subject or chain |
| `wallet_frozen` | Emergency freeze blocks signing |
| `budget_exceeded` | Per-transaction, daily, monthly, or delegation budget rejected the action |
| `recipient_not_allowed` | Recipient allowlist rejected the transaction |
| `contract_not_allowed` | Contract allowlist rejected the transaction |
| Vault access denied | Grant missing, expired, revoked, or token lacks required scope |

## Billing, Feature Availability, And Rate Limiting

Check:

- tenant billing and plan state allow the feature
- usage has not exceeded plan or quota limits
- request frequency is within configured rate limits
- deployment enables the required feature
- tenant settings enable the required feature
- required infrastructure is configured, such as email, SMS, OpenAPI, wallet,
  HSM/TSS, SCIM, or Dynamic Client Registration

Do not assume rate-limit numbers are the same across deployments.

Common symptoms:

| Symptom | Likely cause |
|---|---|
| `429 Too Many Requests` | Endpoint or tenant-level rate limit exceeded |
| `billing_feature_disabled` | Feature not available for plan, tenant, or deployment |
| `billing_suspended` | Billing state blocks billable operations |
| Endpoint returns not implemented or unavailable | Feature is not enabled or required infrastructure is missing |

## Escalation Guidelines

Escalate when:

- production traffic is affected
- a security incident or suspected compromise is involved
- documented behavior and actual behavior differ
- the issue cannot be reproduced or isolated after completing the relevant
  troubleshooting section
- the fix requires platform configuration, tenant policy changes, or code changes

Before escalating:

- complete the relevant section above
- reproduce with the smallest request or flow possible
- collect the safe evidence listed in [What To Collect Before Debugging](#what-to-collect-before-debugging)
- include sanitized error JSON, `x-request-id`, timestamps, tenant context, and
  affected surface
- describe what changed recently, such as redirect URI, SSO provider metadata,
  role mapping, webhook endpoint, agent key, wallet policy, or deployment config

Never include raw tokens, secrets, MFA codes, recovery codes, or unnecessary PII
in escalation notes.

## Related Pages

| Need | Read |
|---|---|
| Prepare integration inputs | [For Developers](../developers/index.md) |
| Add login to an app | [Add SigID Login](../developers/add-login.md) |
| Configure OAuth behavior | [OAuth And OIDC](oauth-oidc.md) |
| Validate API tokens | [Verify Tokens](../developers/verify-tokens.md) |
| Understand APIs and errors | [API And SDK Reference](api-sdk-reference.md) |
| Configure workspace setup | [Launch Your Workspace](../business/launch-workspace.md) |
| Manage users | [Users And Login Methods](../business/users-login-methods.md) |
| Manage organizations and SSO | [Organizations And SSO](../business/organizations-sso.md) |
| Verify webhook signatures | [Webhooks](../developers/webhooks.md) |
| Debug agent authentication | [Agent And MCP Auth](../developers/agents-mcp.md) |
| Debug delegation | [OAuth And OIDC](oauth-oidc.md#device-authorization-ciba-and-token-exchange) |
| Debug wallets | [Security Model](security-model.md#agent-and-wallet-safeguards) |
