Flows / Human present

Device authorization grant

For agents with no browser of their own: show a code, let the person approve on another device, and poll.

Based onRFC 8628published August 2019Guide reviewedNovember 2026

Sources and review details
This page
Implementation guideAn explanation, not a specification
Primary specification
Device Authorization GrantRFC · August 2019
5 required references
5 published1 more listed as optional or background
Human involvement
Human present
Review
Checked against sources in November 2026How it was checked

A coding agent in a remote container, a CLI over SSH, a job in a sandbox: none of them can open a browser window or receive a redirect. The device authorization grant splits the flow across two devices. The agent displays a short code and a URL; the user opens that URL on a phone or laptop, signs in, and types the code. Meanwhile the agent polls the token endpoint until the answer arrives.

It is simple and widely deployed, which is why it is the first thing people reach for with headless agents. It is also the flow most abused for phishing, because the person approving has no technical proof that the code on their screen came from the session they think it did.

Step by step

10 steps between 4 parties. Each step shows the message and who holds which credential afterward. Use ←→ or select any arrow.

Sequence diagram4 participants, 10 steps
  • Direct call
  • Via the user’s browser or device
  • Response
  • Out of band

Drag to see every party and step. Tap a step to jump to its explanation.

1Device authorizationrequest2device_code,user_code, URL3Show code and URL4Open URL, sign in, enter code5Poll token endpoint6authorization_pending7Approve the request8Poll again9Access token(+ refresh)10API call with Bearer token

  1. 1Headless agent to Authorization serverDirect call

    The agent asks to start a device flow

    No user is involved yet. The agent identifies itself and says what it wants.

    POST /device_authorization HTTP/1.1
    Host: auth.example
    Content-Type: application/x-www-form-urlencoded
    
    client_id=cli-agent
    &scope=repo.read
  2. 2Authorization server to Headless agentResponse

    The server returns two codes

    The device_code is a long secret the agent keeps and uses to poll. The user_code is short enough to type. verification_uri_complete embeds the user code so it can be rendered as a QR code.

    {
      "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
      "user_code": "WDJB-MJHT",
      "verification_uri": "https://auth.example/device",
      "verification_uri_complete": "https://auth.example/device?user_code=WDJB-MJHT",
      "expires_in": 600,
      "interval": 5
    }

    Who holds what after this step

    Headless agent
    newdevice_code

    Parties not listed hold none of this flow’s credentials at this point.

  3. 3Headless agent to UserOut of band

    The agent shows the code

    In a terminal, a chat message, or a QR code. This hop is the weak point: nothing technical ties the code the user sees to the agent they intend to authorize. Whatever channel carries it is the channel an attacker will imitate.

    To sign in, open https://auth.example/device
    and enter the code  WDJB-MJHT

    Who holds what after this step

    Headless agent
    device_code

    Parties not listed hold none of this flow’s credentials at this point.

  4. 4User to Authorization serverVia the user’s browser or device

    The user signs in on a second device

    The user authenticates in a real browser, with whatever factors the server requires, then enters the code. The server looks up the pending request and shows what is being asked for.

    Who holds what after this step

    Headless agent
    device_code

    Parties not listed hold none of this flow’s credentials at this point.

  5. 5Headless agent to Authorization serverDirect call

    The agent polls

    While the user is busy, the agent asks the token endpoint whether a decision has been made, no more often than interval seconds. The resource parameter names the API the token is for. RFC 8707 defines it on token requests for every grant type; RFC 8628 gives the device authorization request only client_id and scope.

    POST /token HTTP/1.1
    Host: auth.example
    Content-Type: application/x-www-form-urlencoded
    
    grant_type=urn:ietf:params:oauth:grant-type:device_code
    &device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
    &client_id=cli-agent
    &resource=https://git.example/api

    Who holds what after this step

    Headless agent
    device_code

    Parties not listed hold none of this flow’s credentials at this point.

  6. 6Authorization server to Headless agentResponse

    Not yet

    The expected answer until the user finishes. Other answers: slow_down (back off), access_denied (the user said no), expired_token (start again).

    { "error": "authorization_pending" }

    Who holds what after this step

    Headless agent
    device_code

    Parties not listed hold none of this flow’s credentials at this point.

  7. 7User to Authorization serverVia the user’s browser or device

    The user approves

    A good approval screen names the client, says where the request came from, and lists the scopes in plain language. It is the user’s only chance to notice that they did not start this.

    Who holds what after this step

    Headless agent
    device_code

    Parties not listed hold none of this flow’s credentials at this point.

  8. 8Headless agent to Authorization serverDirect call

    The agent polls again

    Same request as before.

    Who holds what after this step

    Headless agent
    device_code

    Parties not listed hold none of this flow’s credentials at this point.

  9. 9Authorization server to Headless agentResponse

    The server issues tokens

    From here on the agent is in the same position as after an authorization code flow: a short-lived access token and usually a refresh token.

    Who holds what after this step

    Headless agent
    newaccess tokennewrefresh tokenused updevice_code

    Parties not listed hold none of this flow’s credentials at this point.

  10. 10Headless agent to APIDirect call

    The agent calls the API as the user

    The API sees an ordinary access token. It cannot tell that the approval happened on a different device from the one making the call.

    Who holds what after this step

    Headless agent
    access tokenrefresh token

    Parties not listed hold none of this flow’s credentials at this point.

Watch out for

  • Device-code phishing. An attacker starts the flow themselves and sends the victim the code. The victim approves; the attacker’s agent gets the token. Show the client name, location and requested scopes prominently, and keep codes short-lived.
  • If the agent runs on the same machine as a browser, use authorization code with PKCE and a loopback redirect instead. The redirect binds the approval to the session; a typed code does not.
  • Polling too fast earns a slow_down error. Respect interval.
  • The token lands in a headless environment. Plan for where it is stored and how it is revoked when the container goes away.

Device flow or CIBA?

Both decouple the device that needs a token from the device where the person approves. In the device grant the user carries a code from the agent to the server. In CIBA the server reaches out to a user it already knows. Use the device grant to sign in someone who is sitting there; use CIBA to ask a known user for approval when they are somewhere else.

Standards in play

See the full tracker for status and links.

Required

What the flow implements, shows in a step, or must support. These decide its maturity rating.

RFCRFC 10027

Security of Cross-Device Flows

Covers the consent-phishing risks of device codes and backchannel prompts, which is how agents usually reach humans. New in 2026.

RFCRFC 8707

Resource Indicators

Required by MCP. An agent talks to many servers; this is what stops a token for one being replayed at another.

RFCRFC 6750

Bearer Token Usage

The default way agents present tokens, and the thing proof-of-possession schemes are trying to replace.

Background

Related reading. Not what the flow implements, and not used in a step.

WG draftdraft-ietf-oauth-v2-1

OAuth 2.1

The baseline MCP profiles. Worth knowing that the normative base of most agent authorization is still, formally, a draft.