Device Authorization Grant
ProAuth supports the OAuth 2.0 Device Authorization Grant defined by RFC 8628. Use this flow for clients that cannot comfortably open an embedded browser or enter a password directly, such as CLI tools, smart TVs, kiosks, and IoT devices.
The device client receives a device_code, a short user_code, and a verification URL. The user opens the verification URL on another device, signs in, reviews consent, and approves or denies the request. The device client polls the token endpoint until ProAuth can issue tokens or returns a final error.
Flow
Client Configuration
Enable the grant on the client application with the v2 Management API field allowDeviceAuthorizationGrant. The v1 Management API does not expose this setting.
Public clients may call the device authorization endpoint with client_id only. Confidential clients use the configured client authentication method from ClientAppAuthenticationConfiguration, including client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt, tls_client_auth, and self_signed_tls_client_auth.
{
"name": "Example CLI",
"isPublic": true,
"allowDeviceAuthorizationGrant": true,
"scopeFilterEnabled": true,
"resourceFilterEnabled": true
}Requested scopes and resources are still validated against the client application's configured filters. Request openid to receive an ID token and request offline_access to receive a refresh token.
Device Authorization Request
POST /{tenantKey}/connect/device HTTP/1.1
Content-Type: application/x-www-form-urlencoded
client_id=example-cli&scope=openid%20profile%20offline_access&resource=https%3A%2F%2Fapi.example.comSuccessful response:
{
"device_code": "opaque-high-entropy-device-code",
"user_code": "ABCD-1234",
"verification_uri": "https://idp.example.com/connect/verify",
"verification_uri_complete": "https://idp.example.com/connect/verify?user_code=ABCD-1234",
"expires_in": 600,
"interval": 5
}The user_code is short, uppercase, and case-insensitive. ProAuth stores only hashes of the device code and user code.
User Verification
Users can open either the tenant-specific verification URL or the root verification URL:
/{tenantKey}/connect/verify/connect/verify
When verification_uri_complete is used, the user_code is prefilled. Root verification resolves the active user code to the correct tenant before continuing through the normal login, MFA, and consent checks.
The user may approve or deny the request. Approval stores a protected authenticated principal for the pending device session. Denial makes token polling fail with access_denied.
Token Polling
POST /{tenantKey}/connect/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code
&client_id=example-cli
&device_code=opaque-high-entropy-device-codePolling responses follow RFC 8628:
| Condition | OAuth error |
|---|---|
| User has not completed verification | authorization_pending |
| Client polls faster than the current interval | slow_down |
| Device session expired | expired_token |
| User denied the request | access_denied |
| Device code is missing, invalid, belongs to another client, or was already redeemed | invalid_grant |
After a slow_down response, ProAuth increases the current polling interval by 5 seconds. Clients should wait at least the latest interval before polling again.
Tenant Options
| Option | Default | Description |
|---|---|---|
DeviceCodeLifetime | 00:10:00 | Lifetime of the device authorization session, including both the device code and user code. |
DeviceCodePollingInterval | 00:00:05 | Initial minimum polling interval returned as interval. |
Discovery Metadata
The OpenID Connect discovery document advertises:
device_authorization_endpointurn:ietf:params:oauth:grant-type:device_codeingrant_types_supported
Device clients should prefer the discovery metadata instead of constructing endpoint URLs manually.