Use the device-code flow only for terminal or headless clients that cannot host a browser, register the app as public, and keep the browser approval step explicit. The CLI should display the user code, poll at the advised interval, and exchange the code only after user approval completes.
When device-code login is the right OAuth pattern for a CLI
The device code grant exists for one narrow reason: a client that cannot safely host a browser still needs an OAuth-based way to get user consent. For CLI tools, that usually means the command line is the place to initiate and poll, while the browser remains the place where the user authenticates and approves.
That separation matters because the CLI is usually a public client with no confidential secret to protect. The design goal is not to make the terminal “log in” by itself, but to let the user complete the approval on a trusted browser and then hand the CLI a short-lived authorization result.
In practice, teams should treat the flow as a fallback for terminal-first or headless usage, not as the default authentication design for every developer tool. When a CLI can launch a browser and use a normal authorization-code flow with PKCE, that is generally a better fit for richer user experience and tighter security.
What the CLI must do during the device flow
The CLI should present the user code clearly, point the user at the verification URL, and keep its own local state minimal. It should poll at the server-advised interval rather than inventing its own cadence, because aggressive polling is a common way to create unnecessary load and failure noise.
The browser step must stay explicit. The user should see that they are approving a device or terminal session, not signing into the CLI itself in a way that obscures what is being authorized. That clarity reduces consent mistakes and makes it easier to notice when a request is unexpected.
Once the approval is complete, the CLI should exchange the device code exactly once and then discard any transient material tied to the pending authorization. A robust implementation also handles expiry, cancellation, and denial cleanly so the terminal session does not keep retrying after the server has already invalidated the request.
How to keep the flow safe for users and tenants
The biggest security mistake is treating device code login as “simple login for CLI” without respecting the trust boundary. The browser approval step is what preserves user intent, while the terminal remains a constrained public client that should not store long-lived reusable credentials unless there is a separate, deliberate design for that.
Teams should prefer short-lived access and refresh behavior that fits the product’s threat model, and they should be careful about the scopes granted to a CLI. A shell utility that needs read-only access to one API should not request broad delegated permissions just because device flow makes approval easy.
For OAuth fundamentals, it is worth anchoring implementation decisions to the core framework and current security guidance, especially the device authorization grant and the latest OAuth security best current practice in RFC 6749 and RFC 9700. When teams want a broader implementation reference, OAuth 2.0 and OpenID Connect Guide for Identity Teams is useful for understanding where device flow fits among the other grant types.
Implementation choices that prevent fragile CLI auth
Most device-code failures come from poor client classification, brittle polling logic, or excessive permission design. Register the app as a public client, do not pretend the CLI can safely hold a client secret, and make sure the authorization server’s device-flow settings match the real session timeout and user approval window you want to support.
Teams should also decide up front how they will distinguish “terminal utility” from “browser-capable client” in product architecture. That decision drives whether device flow is the correct default or just an exception path for SSH sessions, containers, remote hosts, or air-gapped administration.
For teams that want to see how OAuth misuse and token theft can turn a convenience flow into a compromise path, the issues described in Microsoft verified publisher OAuth phishing 2022 are a useful reminder that user consent remains a security control, not a formality. The implementation lesson is to keep approval explicit, narrow, and visible to the user.
Risk and Threat Considerations
Device-code login can be abused when users are conditioned to approve prompts without verifying context, or when a hostile app induces approval for a session the user did not start. The risk is not the browser page itself, but the combination of a legitimate-looking verification step and a user who cannot tell whether the terminal request is expected.
Failure mechanism: The attacker relies on consent confusion, code interception, or overly broad authorization requests so that a valid user approval grants access to the wrong party or to more privilege than the CLI actually needs.
Impact: A successful abuse can create unauthorized API access, token theft, or persistent access to the user’s delegated permissions, especially when the approved scopes are wider than the CLI’s real function.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP Non-Human Identity Top 10 and OWASP API Security Top 10 address the attack and risk surface, while NIST SP 800-53 Rev 5 sets the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP Non-Human Identity Top 10 | NHI-04 — Insecure Authentication | CLI device flow depends on correct authentication handling and explicit user approval. |
| NHI-07 — Long-Lived Secrets | Device-code implementations should avoid introducing reusable long-lived client secrets. | |
| Recommendation — Keep the browser approval explicit and avoid treating the CLI as a confidential client. Prefer short-lived credentials and remove any transient authorization material after use. | ||
| OWASP API Security Top 10 | API2 — Broken Authentication | CLI OAuth mistakes can weaken authentication and enable unauthorized token use. |
| API6 — Unrestricted Access to Sensitive Business Flows | Overbroad scopes during device approval can expose more API capability than the CLI needs. | |
| Recommendation — Validate the OAuth client type and reject authentication designs that depend on shared secrets for public CLIs. Limit scopes so the CLI only receives access to the business flow it actually requires. | ||
| NIST SP 800-53 Rev 5 | IA-2 — Identification and Authentication (Organizational Users) | User approval in device flow still depends on strong user authentication at the browser step. |
| IA-5 — Authenticator Management | Device flow depends on careful handling of codes, tokens, and other authenticators. | |
| Recommendation — Require strong user authentication before issuing delegated access. Manage OAuth codes and tokens as authenticators with strict lifetime and reuse limits. | ||
Practitioner Guidance
What to verify: Confirm that the CLI cannot host a browser, that the app is registered as a public client, and that the authorization server returns explicit device-flow timing and expiry behavior your tool can respect.
Decision rule: If the tool can reliably use a browser and PKCE, prefer that route; reserve device code login for terminal, remote, or headless contexts where browser-based auth is genuinely impractical.
Common mistake: Do not ask for broad delegated scopes just because the flow is convenient, and do not keep polling after denial or expiry, because both patterns create avoidable user confusion and operational noise.
Practitioner takeaway: The right device-code implementation is one that preserves user intent, limits scope, and behaves like a constrained public client, not one that tries to make the terminal behave like a browser.
Related resources from NHI Mgmt Group
- How should security teams implement OAuth device flow for CLI tools without creating new credential risks?
- How should security teams implement Client ID Metadata Documents?
- What breaks when device code login is treated like a normal CLI convenience feature?
- How should security teams handle authentication for CLI tools without embedding browser login in the terminal?