Skip to content

Device authorization flow

View as Markdown

Device authorization is for clients that cannot safely hold an application client-auth private key: CLIs, launchers, terminal tools, shared devices, and other public clients. The client asks Sudomimus for a short-lived deviceCode / userCode pair, shows the user a code, sends them to the browser, and polls until approval turns into ordinary Sudomimus application tokens.

For implementation, see the SDK overview and the language page for your runtime. Follow the available language guides or the protocol examples below; confirm package availability in the SDK source documentation.

The flow follows the OAuth 2.0 Device Authorization Grant (RFC 8628) model: the initiating client receives a device code and a user code, the user approves in a browser-capable user agent, and the client polls until the authorization is complete. Sudomimus keeps the standard device-flow shape while returning Sudomimus application tokens.

This is a separate integration path from Connect and Native direct-issue:

Path What proves the request
Connect A client-auth JWT signed by the application’s private key
Native direct-issue A platform credential such as a Steam ticket or AccessKey secret
Device authorization A public client starts a code session; the browser user approves it

The public HTTP surface is device-api.sudomimus.com. The browser approval page is still hosted by via.sudomimus.com.

Step Actor Endpoint Result
1. Start Client device-api POST /device-authorize { deviceCode, userCode, verificationUri, verificationUriComplete, expiresIn, interval }
2. Approve User in browser via.sudomimus.com/device The user signs in, confirms the displayed code, and approves or denies
3. Poll Client device-api POST /device-token Pending state, polling instruction, denial, expiry, or { accessToken, refreshToken }
4. Continue Client session-api POST /refresh Later token rotation uses the normal Session API operations
sequenceDiagram
    autonumber

    participant Client as Public client
    participant Browser as User browser
    participant Device as Device API
    participant Via as via.sudomimus.com
    participant Session as Session API

    Client->>Device: POST /device-authorize<br/>applicationAnchor
    Device-->>Client: deviceCode + userCode<br/>verificationUri + interval
    Client-->>Browser: Open verificationUri<br/>show userCode

    par Browser approval
        Browser->>Via: Open /device and confirm userCode
        Note over Browser,Via: User authenticates and approves
        Via-->>Browser: Approved, return to the client
    and Client polling
        loop Until approval completes
            Client->>Device: POST /device-token<br/>deviceCode
            Device-->>Client: authorization_pending or slow_down
        end
    end

    Client->>Device: POST /device-token<br/>deviceCode
    Device-->>Client: accessToken + refreshToken<br/>device session consumed

    Client->>Session: Later: POST /refresh<br/>refreshToken
    Session-->>Client: new accessToken + rotated refreshToken

Only the client sees deviceCode. Only the user sees and confirms userCode. A successful /device-token response consumes the device session, so the same deviceCode cannot mint another token pair.

The client starts by posting its application anchor:

Terminal window
curl -X POST https://device-api.sudomimus.com/device-authorize \
-H "Content-Type: application/json" \
-d '{
"applicationAnchor": "your-application"
}'

Successful response:

{
"applicationAnchor": "your-application",
"deviceCode": "dvc_...",
"userCode": "ABCD-EFGH",
"verificationUri": "https://via.sudomimus.com/device",
"verificationUriComplete": "https://via.sudomimus.com/device?user_code=ABCD-EFGH",
"expiresIn": 600,
"interval": 5
}

/device-authorize does not accept a client-auth JWT. The application opts in through configuration instead: it must have an enabled Layer 3 DEVICE_CODE ReturnRule. If that rule is missing, the request is refused.

Show the userCode clearly in the client UI and ask the user to open the browser approval page:

Visit https://via.sudomimus.com/device
Enter code: ABCD-EFGH

When possible, open verificationUriComplete instead. It pre-fills the code and is also the best target for QR-code or clickable terminal output:

https://via.sudomimus.com/device?user_code=ABCD-EFGH

The browser page displays the application and code again before approval. The user should compare the browser code with the code shown by the client. The browser never receives deviceCode and never displays access or refresh tokens; it only approves or denies the pending session.

The client polls /device-token with the private deviceCode:

Terminal window
curl -X POST https://device-api.sudomimus.com/device-token \
-H "Content-Type: application/json" \
-d '{
"deviceCode": "dvc_..."
}'

Poll no faster than the returned interval. While the user is still working, /device-token returns an OAuth-style polling error:

{
"error": "authorization_pending"
}

After approval, the same endpoint returns ordinary Sudomimus application tokens:

{
"applicationAnchor": "your-application",
"accessToken": "...",
"refreshToken": "...",
"claims": {
"email": { "requirement": "OPTIONAL", "state": "GRANTED" },
"firstName": { "requirement": "OFF", "state": "UNKNOWN" },
"lastName": { "requirement": "OFF", "state": "UNKNOWN" },
"staticAvatar": { "requirement": "SYNTHETIC_ONLY", "state": "UNKNOWN" },
"animatedAvatar": { "requirement": "OFF", "state": "UNKNOWN" }
}
}

The claims block explains the application’s claim policy joined with the user’s standing sharing decision. The actual token payload follows the normal Sudomimus token rules.

4. Use Session API for later token operations

Section titled “4. Use Session API for later token operations”

Device authorization only owns the initial public-client exchange. Once /device-token succeeds, the refresh token belongs to the normal Sudomimus application session model.

Use Session API token operations afterward:

  • POST /refresh to rotate the refresh token and issue a new access token.
  • POST /logout to terminally revoke the current ApplicationSession.
  • POST /introspect to inspect a token.
  • POST /revoke-all for application-level session revocation.

See Managing sessions for those operations and Device polling and errors for the polling state machine.

New applications start in DRAFT. Configure the rules below, then have an organization OWNER take the application live before calling /device-authorize. Device authorization requires an ACTIVE application and available parent organization and sector.

An application must allow the browser-side authentication and realization checks it wants users to pass:

Layer Requirement
Layer 1 Existing authentication methods such as email OTP or passkeys
Layer 2 Existing identity rules that allow the realized account
Layer 3 A DEVICE_CODE ReturnRule

DEVICE_CODE is a Layer 3 return method, not a new authentication method. The user still signs in through the application’s ordinary Layer 1 methods and is still checked against Layer 2 before the device session can be approved.

Use device authorization when your client is public and cannot keep a client-auth private key secret. That is the usual fit for a CLI distributed to users, a launcher installed on a desktop, a terminal-only environment, or a shared-screen device that needs the user to finish sign-in on another browser-capable device.

Use Connect browser polling instead when you have a confidential application backend that can sign /establish. Use Native direct-issue when the client has a platform credential such as a Steam ticket or a pre-issued AccessKey.

The raw endpoint contract is published in the Device API reference.