---
title: "Device authorization request (RFC 8628 §3.1)"
method: POST
path: "/oauth/device_authorization"
tags: ["OAuth"]
---

# Device authorization request (RFC 8628 §3.1)

`POST /oauth/device_authorization`

## Request

- Base URL: `https://api.infolang.ai`
- URL: `https://api.infolang.ai/oauth/device_authorization`
- Auth: none declared

Starts the device flow, for a client that cannot open a browser — a CLI on a headless box, where a loopback redirect is no help because there is no browser on that machine at all.

Returns a `device_code` the client keeps and polls with, and a `user_code` it PRINTS for a human to type at `verification_uri` (the console's `/activate`). `verification_uri_complete` carries the code pre-filled (§3.3.1) — a convenience, never a substitute: a client must always print the URI and the code, since the premise of this flow is a machine that may not be able to open anything.

The client must be registered for the device grant. The registration response is the authoritative record of what a client may do (RFC 7591 §3.2.1), so a client holding only `authorization_code` is refused with `unauthorized_client`.

**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.

Public — no credential. That is not an oversight: a client cannot authenticate before it has a token, which is the entire purpose of this surface.

## Response `200`

The pending device authorization (`Cache-Control: no-store`)

- object
  - `device_code` string, required
  - `user_code` string, required
  - `verification_uri` string, required
  - `verification_uri_complete` string, required
  - `expires_in` number, required
  - `interval` number, required

## Other responses

- `400`: `invalid_request`, `invalid_client`, `unauthorized_client` (not registered for the device grant) or `invalid_scope`
- `401`: `invalid_client` — a confidential client failed to authenticate
- `500`: `server_error` — the pending grant could not be stored

---

[API](https://skmtc.dev/infolang/apis/infolang-api.md) · [All operations](https://skmtc.dev/infolang/apis/infolang-api/llms.txt) · [OpenAPI document](https://skmtc.dev/infolang/apis/infolang-api/revisions/d04bf6de72c8?raw)
