OAuth

Approve or deny a device (console only)

The device flow's POST /oauth/consent: same session gate, same attenuation rules, and literally the same consent evaluation code. The difference is structural — there is no redirect, because no browser is waiting. The device learns the outcome by polling.

A user cannot consent to more than they hold. The approved scopes must be within what the consenter's roles permit on the chosen workspaces; max_role is a ceiling only, since Kairos takes min(grant role, max_role) per workspace.

Single use, both ways. The approve/deny transition is an atomic conditional update, so a double-clicked button, a replay, or an approve racing a deny resolves to exactly one outcome and the rest get 404. A denial is terminal too — a human who refuses cannot be talked into retrying a code an attacker still holds.

The approver's IP and User-Agent are recorded alongside the device's, and both appear on the oauth.device_approved activity row.

Device-code phishing is actively exploited. The attack needs no vulnerability: an attacker starts the flow on their own machine, gets a real user_code, and talks a victim into entering it — every URL the victim sees is genuine, and what they approve is the attacker's device. The countermeasures are the implementation's: a 600-second expiry, single-use codes, a five-attempt entry ceiling per console principal, and an IP/User-Agent record of BOTH legs on the grant so a mismatch is visible to anomaly review.

post/oauth/device/decision

Request

  • Base URL: https://api.infolang.ai
  • URL: https://api.infolang.ai/oauth/device/decision
  • Auth: HTTP bearer

Request body

user_codestring required
denyboolean
workspacesstring[]
scopesstring[]
max_role'Owner' | 'Admin' | 'Member' | 'ReadOnly'

Response

The decision that was recorded

approvedboolean required
client_namestring nullable required

Changes

No recorded changes to this operation across all 1 revision of this API.