Device Authorization Flow
OAuth 2.0 Device Authorization Flow support in the OIDC module.
This page describes the OIDC module support for OAuth 2.0 Device Authorization Flow.
The user-facing verification flow is configured on the authenticator side. See Device Authorization Flow authenticator.
Device Authorization Flow is useful when the relying party cannot do a normal redirect-driven browser flow, for example on:
- TV devices
- kiosks
- limited-input devices
- similar cross-device login scenarios
The relying party starts the flow through device_authorize, the user completes authentication through a separate verification flow, and the relying party polls the token endpoint until the result is ready.
Endpoints
Section titled “Endpoints”The OIDC module adds support for:
POST /device_authorizePOST /tokenwithgrant_type=urn:ietf:params:oauth:grant-type:device_code
The OIDC discovery metadata should also expose a device_authorization_endpoint.
Module configuration
Section titled “Module configuration”| Name | Description | Default value | Mandatory |
|---|---|---|---|
device_verification_uri | User-facing verification URI returned to the relying party in the device_authorize response. This must be configured when at least one RP has device_flow.enabled=true. | N/A | true |
discovery_meta.device_authorization_endpoint | Device Authorization endpoint published in discovery metadata. | N/A | true |
discovery_meta.grant_types_supported | Should include urn:ietf:params:oauth:grant-type:device_code when Device Flow is enabled. | N/A | true |
rps[].device_flow.enabled | Enables Device Authorization Flow for the relying party. | false | false |
rps[].device_flow.interval | Polling interval returned to the relying party. | 5 | false |
rps[].device_flow.device_code_ttl | Device code time to live in seconds. | 1800 | false |
* mandatory when Device Flow is enabled for at least one relying party
{ "name": "OIDCModule", "enabled": true, "config": { "http_context": "/oidc", "http_port": 8080, "tenant_op_path": "/tenant1", "device_verification_uri": "https://login.example.com/access/authn/device", "discovery_meta": { "issuer": "https://login.example.com/oidc/tenant1", "token_endpoint": "https://login.example.com/oidc/tenant1/token-endpoint", "device_authorization_endpoint": "https://login.example.com/oidc/tenant1/device_authorize", "jwks_uri": "https://login.example.com/oidc/tenant1/.well-known/openid-configuration/jwks", "grant_types_supported": [ "authorization_code", "urn:ietf:params:oauth:grant-type:device_code" ] }, "keystore": { "path": "/fortified_test/keystore.p12", "password": "secret", "type": "PKCS12" }, "sign_jwt_keystore_password": "secret", "sign_jwt_keystore_alias": "jwt", "rps": [ { "client_id": "tv-client", "client_secret": "secret", "redirect_uri": [ "https://www.example.com/callback" ], "device_flow": { "enabled": true, "interval": 5, "device_code_ttl": 1800 } } ] }}device_authorize request
Section titled “device_authorize request”Example:
POST /oidc/tenant1/device_authorizeAuthorization: Basic dHYtY2xpZW50OnNlY3JldA==Content-Type: application/x-www-form-urlencoded
scope=openidEquivalent curl request:
curl -u tv-client:secret \ -X POST \ -d "scope=openid" \ https://login.example.com/oidc/tenant1/device_authorizedevice_authorize response
Section titled “device_authorize response”Example:
{ "device_code": "f2d189221cda27d41b6894b0cb055261", "user_code": "4B15-55ED", "verification_uri": "https://login.example.com/access/authn/device", "verification_uri_complete": "https://login.example.com/access/authn/device?user_code=4B15-55ED", "expires_in": 1800, "interval": 5}Token polling
Section titled “Token polling”The relying party polls the token endpoint using:
POST /oidc/tenant1/token-endpointAuthorization: Basic dHYtY2xpZW50OnNlY3JldA==Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=f2d189221cda27d41b6894b0cb055261Equivalent curl request:
curl -u tv-client:secret \ -X POST \ -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \ -d "device_code=f2d189221cda27d41b6894b0cb055261" \ https://login.example.com/oidc/tenant1/token-endpointPossible responses include:
authorization_pendingslow_downexpired_token- successful token response
Example pending response:
{ "error": "authorization_pending", "error_description": "The end-user has not yet completed the authorization flow"}Example successful response:
{ "access_token": "...", "id_token": "...", "token_type": "Bearer", "expires_in": 60}Session behavior
Section titled “Session behavior”The implementation uses the shared Access session model for:
- device session state
- user-code lookup
- polling status
- completion cleanup
Important behavior:
- the same
user_codecan be used again while the flow is stillPENDING - after the first successful token response, the device-flow session state is cleaned up
- the implementation supports clustered/session-replicated environments
Discovery metadata
Section titled “Discovery metadata”When Device Flow is enabled, discovery metadata should include:
device_authorization_endpoint- the
device_codegrant ingrant_types_supported