Some clients should never ask the user to type a password into them.
That sounds obvious for a smart TV, a kiosk, or an industrial controller with a small screen and no comfortable keyboard. It is just as relevant for command-line tools. A CLI can usually open a browser on a developer workstation, but that assumption breaks down quickly on remote shells, build agents, bastion hosts, locked-down terminals, shared operations consoles, and constrained admin environments.
The OAuth 2.0 Device Authorization Grant gives these clients a safer pattern. The device or tool starts the flow, shows the user a short code and verification address, and polls the token endpoint while the user signs in on a separate browser-capable device. ProAuth 3.0.0 adds this standards-based flow as part of its expanded OAuth and OIDC coverage, described in the ProAuth 3.0.0 release notes.
This is not a replacement for normal browser-based applications. RFC 8628 is explicit about the intended boundary: use device flow when the client lacks a suitable browser or is constrained enough that direct user authentication on that device is impractical. If the application can use the ordinary browser-based OAuth path well, that remains the better default.
The device should not become the login surface
The core problem is not only typing difficulty. It is trust.
If a kiosk asks for a corporate password, the user has to trust the kiosk UI, its software image, its logs, its keyboard path, its maintenance history, and whoever owns the physical environment. If a CLI asks for a password, the user has to trust the terminal session, shell history, wrapper scripts, plugins, screen sharing, and process environment. Some of those environments are perfectly reasonable for short-lived commands. They are not good places to collect primary credentials.
Device Authorization Grant changes the interaction. The constrained client does not collect the password. It receives protocol artifacts from ProAuth, presents a human-readable instruction, and waits. The user completes authentication, MFA, and consent in the normal ProAuth browser experience on a device that can handle it.
sequenceDiagram
autonumber
participant Device as Constrained client
participant ProAuth as ProAuth
participant User as User
participant Browser as Browser
Device->>ProAuth: Request device code
ProAuth-->>Device: device code, user code, URI, interval
Device-->>User: Show URI and user code
User->>Browser: Open verification URI
Browser->>ProAuth: Submit user code
ProAuth->>Browser: Sign in, MFA, consent
loop Poll at returned interval
Device->>ProAuth: Token request with device code
ProAuth-->>Device: pending, slow down, tokens, or final error
end
What the client receives
The device authorization response gives the client a small set of values with different audiences:
| Value | Who uses it | Purpose |
|---|---|---|
device_code | The client | Opaque value sent to the token endpoint while polling. It is not meant for the user. |
user_code | The user | Short code the user enters during verification. ProAuth uses an uppercase code format and treats it case-insensitively. |
verification_uri | The user | Browser address where the user enters the code and completes the verification step. |
verification_uri_complete | The user, when convenient | Verification address that already includes the user code, useful for QR codes or copyable links. |
expires_in | The client | Lifetime, in seconds, of the device authorization session. |
interval | The client | Minimum polling interval, in seconds, before calling the token endpoint again. |
In ProAuth, the configured defaults are documented as a 10-minute DeviceCodeLifetime and a 5-second DeviceCodePollingInterval. The exact values are tenant options, so clients should use the expires_in and interval values from the response instead of hardcoding assumptions.
One implementation detail is worth keeping visible: the ProAuth documentation says the device code and user code are stored as hashes. That does not make the flow self-defending, but it is the right kind of server-side hygiene for values that temporarily connect a device session to a user verification step.
The user-facing step is the security moment
The user experience should be plain and specific:
Open the verification URI shown by ProAuth
Enter code ABCD-1234
Then return to this terminal.
The actual verification page matters more than the terminal text. The user should see the ProAuth-hosted verification page, authenticate through the normal login path, complete MFA or other tenant checks where required, review the request, and approve or deny it.
That review step is not decoration. It is where the user connects the physical or operational context in front of them with the authorization request in the browser. For a CLI, that might be “this terminal wants access to the management API.” For a kiosk, it might be “this station is requesting access for this tenant.” For a device administration workflow, it might be “this controller wants the requested scopes and resource audience.”
ProAuth supports both tenant-specific and root verification routes, and verification_uri_complete can prefill the code. Root verification resolves the active user code to the correct tenant before continuing through normal login, MFA, and consent checks. The device still polls in the background; the user does not handle the device_code.
Polling is part of the contract
Device flow is deliberately asynchronous. The constrained client cannot assume that the browser session can call back into it, so it polls the token endpoint with:
grant_type=urn:ietf:params:oauth:grant-type:device_code- the client identifier, or the configured client authentication for confidential clients
- the
device_code
While the user has not finished verification, ProAuth returns authorization_pending. If the client polls faster than the current interval, ProAuth returns slow_down and increases the current polling interval by 5 seconds. If the user denies the request, polling ends with access_denied. If the device session expires, it ends with expired_token. If the device code is missing, invalid, belongs to another client, or has already been redeemed, the response is invalid_grant.
That behavior is not incidental. It is how RFC 8628 keeps many devices from turning the token endpoint into a busy loop. Clients should wait at least the returned interval, increase their delay after slow_down, and stop polling on final errors. If a network timeout occurs, clients should back off rather than retrying aggressively.
ProAuth enables the grant per client application
In ProAuth, Device Authorization Grant is a client-application-level capability. A client does not get the flow simply because the server supports it. Enable it for the specific client application with the v2 Management API field allowDeviceAuthorizationGrant; the ProAuth documentation notes that the v1 Management API does not expose this setting.
That per-client boundary is important in mixed estates. A browser application, backend automation client, kiosk, and CLI may all belong to the same product family, but they should not inherit the same grant types by accident.
Public clients can call the device authorization endpoint with client_id. Confidential clients use the configured client authentication method from the client application authentication configuration. ProAuth documents support for methods such as client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt, tls_client_auth, and self_signed_tls_client_auth at the device authorization endpoint where client authentication applies.
Scopes and resources are still checked against the client application’s configured filters. Requesting the device flow does not bypass normal client policy. A CLI that needs an ID token requests openid; a client that needs a refresh token requests offline_access; and API access should still be narrowed through scopes, resources, audience checks, and resource-server validation.
Security boundaries to keep
Device Authorization Grant removes the need to collect user credentials on the constrained client. It does not magically make every device trustworthy.
There are several boundaries worth making explicit:
- The user code is intentionally human-sized, so the verification surface needs brute-force protections and a finite lifetime. RFC 8628 calls out user-code rate limiting as a security consideration.
- The device code is an opaque client-side credential for the pending session. Treat it as secret, do not display it to the user, and avoid logging it.
- The polling interval is a security and availability control. Clients that ignore it should receive
slow_down, and well-behaved clients should back off. - Approval binds the resulting tokens to the authenticated user’s decision, but it does not prove the physical device is healthy, patched, or in the right location.
- Normal OAuth controls still apply after tokens are issued: short lifetimes where appropriate, narrow scopes, resource validation, revocation behavior, and resource-server enforcement.
The phishing boundary also deserves attention. A malicious actor can try to trick a user into entering a code for the attacker’s device session. Good verification screens reduce that risk by showing enough context for the user to recognize what they are approving. Operational guidance should be just as direct: only enter codes when you initiated the device login and the device or CLI in front of you is showing the same request.
Where this fits
Device Authorization Grant is a good fit for CLIs, kiosks, smart-TV-style applications, industrial devices, and IoT administration experiences where the client can make outbound HTTPS requests and display a URI plus code, but should not handle the user’s password directly.
It is a poor fit when the application already has a capable browser interaction model. A desktop or mobile app that can use the standard browser-based authorization code flow should usually do that. A backend service with no user present should use the appropriate non-user grant or client authentication pattern instead. Device flow sits in the middle: there is a real user, but the client in front of them is not the right place for the login ceremony.
For ProAuth implementations, start with the Device Authorization Grant documentation, then confirm the broader v3 context in the ProAuth 3.0.0 release notes. For the protocol background and security considerations, read RFC 8628.