Native claims and the Errand
Steam ticket and AccessKey direct-issue authenticate without an application login page. That keeps the happy path short, but it also means the client cannot display a consent form or ask the user to complete missing profile data.
This page covers both sides of that constraint:
- Choose claim policies that fit a non-interactive client.
- Handle the Errand browser handoff when a required real claim cannot yet be issued.
The shared policy and consent model is documented in Identity claims and sharing.
Choose a native claim policy
Section titled “Choose a native claim policy”| Policy | Native direct-issue behavior |
|---|---|
| Off | Never requested. |
| Optional | Shared only if the user already granted it. Never blocks, so a native-only user may never be prompted. |
| Required | Guaranteed present with real data. Missing consent or data returns 403 with an Errand. |
| Synthetic | Guaranteed present, using real data when granted and a stable placeholder otherwise. Never blocks and never creates an Errand. |
For most native integrations, prefer SYNTHETIC over REQUIRED unless you specifically need verified real data.
- Need a stable name or email-shaped value, and a placeholder is acceptable: use
SYNTHETIC. - Need a real verified email for delivery or reconciliation: use
REQUIREDand implement the Errand flow. - Want real data when already granted but can continue without it: use
OPTIONAL.
If every requested claim is OFF or SYNTHETIC, claim policy can never force direct-issue into a browser handoff.
Synthetic names are generated placeholders. Synthetic emails use a stable …@proxy.sudomimus.email address. Proxy delivery is best-effort, not guaranteed, and OIDC exposes synthetic email with email_verified: false.
The Errand
Section titled “The Errand”An Errand is short-lived account remediation, not token issuance. When direct-issue cannot satisfy a required claim, its 403 response gives the client a browser URL. The user completes consent or missing profile work there, then the client retries the original direct-issue.
Only two claim-gate reasons carry an Errand:
403 reason | Meaning | Browser work |
|---|---|---|
ClaimConsentRequired | A required claim has not been granted. | Grant consent and, when necessary, first add the missing data. |
RequiredClaimDataMissing | Consent exists, but the account lacks the real value. | Register an email or complete the missing name. |
Other 403 responses, such as rule denial or a disabled account, are terminal and do not include an Errand.
Handoff response
Section titled “Handoff response”{ "reason": "ClaimConsentRequired", "claims": { "email": { "requirement": "REQUIRED", "state": "UNKNOWN" }, "firstName": { "requirement": "OPTIONAL", "state": "UNKNOWN" }, "lastName": { "requirement": "OFF", "state": "UNKNOWN" } }, "errand": { "errandKey": "ernd_...", "url": "https://via.sudomimus.com/errand?key=ernd_...", "expiresAt": "2026-06-10T12:30:00Z" }}- Open
errand.urlin the user’s system browser. - Treat
errandKeyas a bearer secret. It is also used to poll status. - The Errand is single-use and expires after 30 minutes.
Client loop
Section titled “Client loop”native client ── direct-issue ──▶ 403 { reason, claims, errand } │ ├── open errand.url in the system browser ├── poll GET /errand/{errandKey}/status └── on COMPLETED, retry direct-issue once ──▶ 200 { tokens, claims }Polling is optional. A client may instead ask the user to confirm that they finished in the browser before retrying.
curl https://native-api.sudomimus.com/errand/ernd_.../status# → { "status": "PENDING" }# → { "status": "COMPLETED" }# → { "status": "EXPIRED" }Poll about every two seconds with a sensible overall timeout. EXPIRED deliberately covers unknown, malformed, consumed, and genuinely expired keys; rerun direct-issue to obtain a fresh handoff. The status endpoint never issues tokens.
Retries normally return the same live Errand when it has at least 15 minutes remaining and the required work has not changed. This prevents an eager retry loop from splitting user progress across multiple URLs.
Security behavior
Section titled “Security behavior”- Consent only: no additional sign-in is required because the credential holder already proved control of a token-minting credential.
- Writing identity data: the browser requires sign-in, and the signed-in account must match the account resolved from the Steam ticket or AccessKey.
- Optional and synthetic claims never create an Errand.
- Connect
/refreshand OIDC/tokendo not embed Errand handoffs. A native session blocked during refresh recovers by running direct-issue again.
Related
Section titled “Related”- Native integration — browser polling, Steam ticket, and AccessKey flows.
- Identity claims and sharing — the shared policy, grant, and inclusion model.
- Tokens and verification — the tokens issued after the claim gate is satisfied.