Skip to content

Connect flow

View as Markdown

This page covers the Connect protocol: the browser-mediated Sudomimus flow used when your application wants direct control over the login round-trip. Connect speaks JSON over HTTPS, so any backend language with an HTTP client works; examples below are in curl, Node.js, Python, and Go.

For production code, prefer an official SDK where one exists. Start with the SDK overview or jump to the TypeScript SDK for @sudomimus/connect.

If you’re building a native client (desktop, game, CLI), see Native clients. For OIDC, see OIDC relying parties.

Tabs are synchronised across the page: pick your language once and every block below switches with it.

Before starting login, configure the rules and credentials for your chosen flow, then have an organization OWNER take the application live. New applications remain DRAFT until explicitly activated; login requires ACTIVE and available parent organization and sector.

Phase Initiator Endpoint Result
1. Establish Application backend connect-api POST /establish { exposureKey, hiddenKey }
2. Authenticate Browser via.sudomimus.com The user completes an allowed challenge
3. Redeem Application backend connect-api POST /redeem { accessToken, refreshToken }
4. Refresh Application backend session-api POST /refresh A new access token and rotated refresh token

The sequence below shows the standard CALLBACK path used by the examples on this page:

sequenceDiagram
    autonumber

    participant App as Application backend
    participant Browser as User browser
    participant Connect as Connect API
    participant Via as via.sudomimus.com
    participant Session as Session API

    App->>Connect: POST /establish<br/>client-auth JWT + return method
    Connect-->>App: exposureKey + hiddenKey

    Note over App: Keep hiddenKey server-side

    App-->>Browser: 302 redirect with exposureKey
    Browser->>Via: Open hosted authentication UI

    Note over Browser,Via: User completes an allowed challenge

    Via-->>Browser: 302 to application callback<br/>exposureKey + confirmationKey
    Browser->>App: GET application callback

    App->>Connect: POST /redeem<br/>exposureKey + hiddenKey + confirmationKey
    Connect-->>App: accessToken + refreshToken

    App->>Session: GET application JWKS
    Session-->>App: Public verification keys
    Note over App: Verify the access token locally

    loop Before the access token expires
        App->>Session: POST /refresh<br/>current refreshToken
        Session-->>App: new accessToken + rotated refreshToken
    end

Three parties split responsibility:

  • Your backend signs /establish, stores hiddenKey, redeems the completed inquiry, and verifies the resulting tokens.
  • The browser carries exposureKey to the hosted authentication UI but never sees hiddenKey.
  • via.sudomimus.com runs the passkey, email OTP, OAuth, or federation challenge and creates confirmationKey only after authentication succeeds.

The first three phases are specific to Connect. OIDC uses authorization code + PKCE, while native direct-issue exchanges a Steam ticket, AccessKey, or PublicKey in one request. After any ordinary application flow has a refresh token, the shared Session API owns refresh, introspection, logout, and revocation.

Your backend asks Connect to open an authentication session. The response gives you an exposure key (passed to the browser) and a hidden key (kept on the server).

Terminal window
curl -X POST https://connect-api.sudomimus.com/establish \
-H "Content-Type: application/json" \
-H "Authorization: SudomimusClientJWT $SUDOMIMUS_CLIENT_AUTH_JWT" \
-d '{
"applicationAnchor": "your-application",
"returnMethods": [
{
"type": "CALLBACK",
"payload": { "callbackUrl": "https://your-app.com/auth/callback" }
}
]
}'

Store hiddenKey against the user’s pending session (e.g. in a server-side store). Send the user to via.sudomimus.com with the exposureKey in the URL.

2. Authenticate — hand off to via.sudomimus.com

Section titled “2. Authenticate — hand off to via.sudomimus.com”

Redirect the user’s browser to via.sudomimus.com with the exposure key. The user completes the passkey or email-OTP challenge there.

# No HTTP call — this is a 302 redirect from your application:
Location: https://via.sudomimus.com/?exposure-key=<exposureKey>

When the user finishes, via.sudomimus.com redirects the browser to your concrete callbackUrl with exposure-key and confirmation-key appended as query parameters. Existing query parameters and fragments are preserved. If the URL already contains either reserved parameter, Connect overwrites it with the current Inquiry value; do not put key templates in the callback URL.

In your callback handler, combine the three keys and exchange them at Connect for an access token plus a refresh token.

Terminal window
curl -X POST https://connect-api.sudomimus.com/redeem \
-H "Content-Type: application/json" \
-d '{
"exposureKey": "...",
"hiddenKey": "...",
"confirmationKey": "..."
}'

The access token is a signed JWT. Read its kid, select that key from the application’s Session JWKS at GET /applications/{applicationAnchor}/jwks.json, verify the signature, and only then trust its claims. Require typ: "vnd.sudomimus.application-access+jwt" for Account-only endpoints. If an endpoint intentionally admits Agent or Automation tokens, also accept typ: "vnd.sudomimus.workload-access+jwt" and handle its act.sub actor. See Tokens and verification for the full verification and cache-refresh recipe.

Before the access token expires, exchange the refresh token at Session API for a fresh access token and a new refresh token. /refresh does not require a client-auth JWT. Refresh tokens are rotated — the token you present is consumed, and the response returns its replacement. Persist the new refreshToken and use it for the next refresh; re-using a spent one revokes the whole session. Near-simultaneous concurrent refreshes of the same token (e.g. multiple tabs) are tolerated and converge on one session; only reuse after the replacement has been issued revokes it.

Terminal window
curl -X POST https://session-api.sudomimus.com/refresh \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "..." }'

For introspection, logout, and account-wide revocation, see Managing sessions.

POST /info returns the localized public profile of an application given its anchor. It does not require a client-auth JWT, so it is safe to call from browsers and untrusted contexts. Signing keys deliberately live on the Session JWKS endpoint, not this metadata route.

Terminal window
curl -X POST https://connect-api.sudomimus.com/info \
-H "Content-Type: application/json" \
-d '{ "applicationAnchor": "your-application", "locale": "en-US" }'

Use GET https://session-api.sudomimus.com/applications/{applicationAnchor}/jwks.json for token verification keys. Cache that response according to Cache-Control, select the JWT’s exact kid, and refresh once when an unknown kid appears.

When your native client can open the user’s system browser but cannot easily receive a callback URL, use the polling flow:

  1. The client backend calls connect POST /establish (signed with the application’s client-auth JWT) declaring a STATUS_POLL return method, and receives { exposureKey, hiddenKey }.
  2. The client opens the system browser pointed at https://via.sudomimus.com/?exposure-key=<exposureKey>.
  3. The user completes the passkey or email-OTP challenge in the browser.
  4. The client polls connect POST /status-poll every few seconds with { exposureKey, hiddenKey }. Once the user finishes, the poll returns { status: "REALIZED", confirmationKey }.
  5. The client then redeems the three keys at connect POST /redeem for { accessToken, refreshToken }.

This works on any platform with a default browser — Windows, macOS, Linux desktop apps, Electron, etc. The application’s Layer 3 rules must allow STATUS_POLL.

The /establish call is the standard client-auth-signed Connect request — see Web applications for the full shape — except the return method is STATUS_POLL:

Terminal window
curl -X POST https://connect-api.sudomimus.com/establish \
-H "Content-Type: application/json" \
-H "Authorization: SudomimusClientJWT $SUDOMIMUS_CLIENT_AUTH_JWT" \
-d '{
"applicationAnchor": "your-application",
"returnMethods": [ { "type": "STATUS_POLL", "payload": {} } ]
}'
# → { "exposureKey": "exp_...", "hiddenKey": "hid_..." }

Then poll /status-poll with those two keys every few seconds. The poll carries no client-auth JWT — possession of the hiddenKey is what authorizes it:

Terminal window
curl -X POST https://connect-api.sudomimus.com/status-poll \
-H "Content-Type: application/json" \
-d '{
"exposureKey": "exp_...",
"hiddenKey": "hid_..."
}'
# While the user is still authenticating in the browser:
# { "status": "PENDING" }
# Once they finish:
# { "status": "REALIZED", "confirmationKey": "cnf_..." }

When the poll returns REALIZED, redeem the three keys at connect POST /redeem for the access and refresh tokens (same /redeem call as the web flow).