Skip to content

Device Authorization Grant (RFC 8628)

Overview

JustIAM supports the OAuth 2.0 Device Authorization Grant (RFC 8628), also known as the Device Flow. This grant type is designed for input-constrained devices (smart TVs, CLI tools, IoT devices) that cannot easily open a browser or securely handle redirects.

Typical use cases:

  • CLI tools authenticating on behalf of the user (e.g., Terraform providers, kubectl plugins)
  • Devices with limited or no keyboard input
  • Headless clients running in terminals

Endpoints

Endpoint Method Description
/oauth2/device_authorization POST Start the device flow — returns device and user codes
/device GET User-facing portal to enter the device code
/device POST Submit the code and approve or deny access
/oauth2/token POST Device polls this endpoint until the user approves

Flow

Device                        JustIAM                      User's Browser
  |                               |                               |
  |-- POST /oauth2/device_auth -->|                               |
  |<-- device_code, user_code ----|                               |
  |                               |                               |
  | (display user_code to user)   |                               |
  |                               |<-- GET /device?user_code=... -|
  |                               |--- HTML form (code entry) --> |
  |                               |<-- POST /device (approve) ----|
  |                               |--- "Access approved" -------> |
  |                               |                               |
  |-- POST /oauth2/token -------->|                               |
  |  (polling with device_code)   |                               |
  |<-- access_token, id_token ----|                               |

Step 1 — Request device and user codes

POST /api/v1/oauth2/device_authorization
Content-Type: application/x-www-form-urlencoded

client_id=my-cli-tool&scope=openid+profile+email

Response:

{
  "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
  "user_code": "BCDF-HJKM",
  "verification_uri": "https://justiam.example.com/device",
  "verification_uri_complete": "https://justiam.example.com/device?user_code=BCDF-HJKM",
  "expires_in": 300,
  "interval": 5
}

The device should display the user_code and verification_uri to the user, or render a QR code using verification_uri_complete.


Step 2 — User activates the device

The user navigates to the verification_uri in their browser, logs in, and enters the user_code. JustIAM shows a confirmation page with the application name and requested scopes. The user approves or denies.


Step 3 — Device polls for a token

The device polls POST /api/v1/oauth2/token every interval seconds until it receives a token or a terminal error:

POST /api/v1/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:device_code
&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS
&client_id=my-cli-tool

Possible responses while polling:

HTTP status error field Meaning
400 authorization_pending User hasn't actioned yet — keep polling
400 slow_down Polling too fast — increase interval
400 access_denied User denied access — stop
400 expired_token Device code expired (> 5 min) — restart
200 Approved — response contains access_token and id_token

Discovery

The device authorization endpoint is advertised in the OIDC discovery document:

GET /.well-known/openid-configuration
{
  "device_authorization_endpoint": "https://justiam.example.com/api/v1/oauth2/device_authorization"
}

Application configuration

Applications using the Device Authorization Grant must have urn:ietf:params:oauth:grant-type:device_code in their grant_types. Public clients (no client secret) are supported and recommended for CLI tools.

Terraform example:

resource "justiam_application" "cli_tool" {
  name          = "my-cli-tool"
  friendly_name = "My CLI Tool"
  type          = "web"
  client_id     = "my-cli-tool"
  grant_types   = ["urn:ietf:params:oauth:grant-type:device_code"]
  allowed_scopes = ["openid", "profile", "email"]
  is_public     = true
  is_active     = true
}

See the full working example at terraform-provider-justiam/examples/modular/applications/device_authorization_cli_0001.tf.


Security considerations

  • Device codes expire after 5 minutes by default.
  • User codes use an unambiguous alphabet (BCDFGHJKLMNPQRSTVWXYZ) to avoid confusion between similar-looking characters (0, O, 1, I, L).
  • The device code is a 32-byte cryptographically random token; the user code is short and human-typeable (format: XXXX-YYYY).
  • Only the user who owns the session at the time of portal approval can approve the request — access_restricted group membership rules apply.
  • Confidential clients must present their client_secret when polling for a token.