Troubleshooting¶
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 |
| OAuth callback includes an error | Callback And Token Exchange Issues |
/oauth/token returns an OAuth error |
Callback And Token Exchange Issues |
API returns 401 or 403 |
Token Validation Issues or Access And Authorization Issues |
/userinfo is missing profile fields |
UserInfo And OIDC Claims |
| SSO loops or does not start | Enterprise SSO And Organizations |
| SCIM user state is wrong | Organizations And SCIM |
| Webhook delivery fails | Webhook And Event Issues |
| Agent or MCP access is denied | Agent And Delegation Issues |
| Session disappears or device state looks wrong | Session And Device Issues |
| Wallet signing or vault access is denied | Wallet And Vault Issues |
| Request is rate-limited or feature is disabled | 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:
{
"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¶
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_idbelongs to the expected tenant applicationredirect_uriexactly matches a registered redirect URI, including scheme, host, path, port, and trailing slashresponse_type=codecode_challenge_method=S256scopecontainsopenidwhen 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¶
Check:
statematches 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_verifiermatches the originalcode_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_typeis 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¶
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_typeis allowed for the route- delegated tokens include expected
actclaims - DPoP proof is present and valid when
cnf.jktis 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 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, orphone - user granted consent for those claims
- user actually has those profile values
- app does not use
/userinfoas 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-ssoreturns 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: falsesemantics 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¶
Check:
- subscription is active
- event type is selected
- receiver URL is HTTPS and reachable
- receiver returns
2xxonly 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.
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, andSameSitesettings 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
- 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 |
| Add login to an app | Add SigID Login |
| Configure OAuth behavior | OAuth And OIDC |
| Validate API tokens | Verify Tokens |
| Understand APIs and errors | API And SDK Reference |
| Configure workspace setup | Launch Your Workspace |
| Manage users | Users And Login Methods |
| Manage organizations and SSO | Organizations And SSO |
| Verify webhook signatures | Webhooks |
| Debug agent authentication | Agent And MCP Auth |
| Debug delegation | OAuth And OIDC |
| Debug wallets | Security Model |