By NHI Mgmt Group Editorial TeamPublished 2025-07-25Domain: Best PracticesSource: WorkOS

TL;DR: Python CLI tools can authenticate users through the OAuth 2.0 Device Authorization Grant, using a browser-based approval step, periodic polling, and token exchange to avoid manual token pasting, according to WorkOS. The pattern is practical for command-line apps, but it also reinforces how device-code flows shift trust, token handling, and user verification into IAM design choices.


At a glance

What this is: This is a step-by-step tutorial on adding browser-based OAuth login to a Python CLI using the device code flow, with a focus on terminal prompts, polling, and token exchange.

Why it matters: It matters because CLI authentication is often where teams quietly introduce unsafe token handling, weak user verification, or brittle device-code polling patterns across human, NHI, and automated workflows.

👉 Read WorkOS' tutorial on adding OAuth device code login to a Python CLI


Context

Python CLI authentication is the point where identity, usability, and token handling collide. When a command-line tool cannot embed a browser, the device code flow gives the user a browser-based approval step while the CLI waits for authorization and then exchanges that approval for tokens.

For IAM teams, the control question is not whether the login works, but whether the flow preserves the right separation between user consent, device trust, and token issuance. The same pattern can be implemented safely or unsafely depending on how the client handles polling, expiration, and token storage.

This is a human identity pattern first, but it has downstream NHI implications because the resulting access token often becomes the credential the CLI uses for later API calls. The security posture of the tool therefore depends on both authentication design and secret handling discipline.


Key questions

Q: How should security teams handle browser-based login for Python CLI tools?

A: Security teams should treat browser-based CLI login as a delegated authentication flow, not as a lower-risk shortcut. The browser step confirms user consent, but the CLI still receives a bearer token that must be protected, expired, and revoked like any other sensitive credential. The main controls are token storage limits, logging hygiene, and strict polling behaviour.

Q: Why do device code flows matter for identity governance?

A: Device code flows matter because they separate user verification from token use. That separation is useful for terminal apps, but it also means governance has to cover the issued token after login, including where it is stored, who can reuse it, and how quickly it expires. The approval screen is only one control point.

Q: What breaks when a CLI logs or stores access tokens carelessly?

A: Careless token handling turns a clean login flow into a credential exposure problem. If access tokens appear in logs, shells, crash dumps, or long-lived files, the resulting credential can be reused outside the intended session boundary. That creates replay risk, weakens accountability, and undermines the trust gain from browser-based approval.

Q: What should teams do after a user completes device-code authentication?

A: Teams should treat the post-authentication token as a governed secret, not as a temporary implementation detail. That means defining where the token is stored, how refresh works, how revocation is triggered, and how the CLI behaves when the token expires. The objective is to keep the credential lifecycle bounded after the browser approval ends.


Technical breakdown

OAuth 2.0 device authorization grant in a CLI

The device authorization grant is designed for input-constrained clients such as terminals, TVs, and other devices that cannot comfortably host a browser. The CLI requests a device code and a user code, then sends the user to a verification page where the browser-based session completes authentication. The CLI never sees the browser credentials directly. Instead, it waits for the authorization server to confirm consent and then returns tokens tied to that approved session. The security boundary is the browser approval step, not the terminal session itself.

Practical implication: treat the browser approval step as the primary control boundary and keep the terminal free of reusable user secrets.

Polling, interval control, and token issuance

Device-code flows rely on polling because the CLI cannot receive a browser redirect. The client repeatedly checks the authorization endpoint using the device code until the user approves, denies, or the code expires. Good implementations respect the interval returned by the server and back off when slow_down appears, because aggressive polling creates unnecessary load and can become a weak operational signal. The important detail is that the CLI is not authenticated until token issuance succeeds, so polling logic is part of the auth control path, not just background plumbing.

Practical implication: enforce server-provided polling intervals and expiry handling so the CLI cannot hammer the authorization endpoint or wait indefinitely.

Access token handling after terminal login

Once the device flow succeeds, the CLI receives an access token and often a refresh token. At that point the authentication problem shifts into session and secret handling. The tool must avoid printing tokens, logging them, or persisting them casually, because a browser-based login does not make downstream credential handling safe by default. In practice, the device code flow authenticates the user, but the CLI still needs separate controls for token storage, lifetime, and revocation posture.

Practical implication: store returned tokens in the narrowest possible local scope and treat them as secrets with explicit lifecycle controls.


Read our 52 NHI Breaches Analysis report for a comprehensive view of breaches impacting Non-Human Identities including AI Agents.


NHI Mgmt Group analysis

Device-code login is a human IAM pattern that inherits NHI secret-handling risk once the token is issued. The article solves the front-end problem of authenticating a CLI user without an embedded browser, but the security boundary moves immediately after approval. Once the access token exists, the CLI becomes a bearer-token consumer, which means token storage, exposure, and reuse matter as much as the login step. Practitioners should treat the post-authentication token as the real asset, not the browser interaction.

Terminal authentication often hides the governance gap between user consent and credential persistence. Device-code flow gives the impression of safer login because the user approves in a browser, yet the CLI still receives a credential that can be copied, cached, or reused. That makes the control problem less about the approval screen and more about whether the organisation has a defined policy for token retention, revocation, and local secret storage. Teams need to govern the resulting credential path, not just the login event.

Named concept: browser-mediated consent, terminal-mediated trust. The article illustrates a common pattern where user approval happens in one channel and credential use continues in another. That split is useful, but it also creates a trust handoff that many programmes do not formally govern. Practitioners should recognise that the browser step proves consent, while the CLI still controls the credential lifecycle after consent ends.

Device-code flows are only as safe as the client discipline around polling and token exposure. Polling is a normal part of the protocol, but it also creates a predictable window in which the client remains unauthenticated and waiting. If the CLI mishandles that waiting state, leaks the returned token, or ignores expiry and slow_down responses, the authentication pattern becomes brittle. The practical conclusion is that secure CLI login requires both protocol correctness and local credential hygiene.

This pattern is a useful bridge between human identity and downstream non-human access. A user may start with browser approval, but the tool often uses the resulting token to call APIs automatically. That is where human IAM decisions start to affect NHI-style access control, because the token can behave like a workload credential once the session is established. Security teams should evaluate the full lifecycle of the issued token, not only the login ceremony.

From our research:

  • Organisations maintain an average of 6 distinct secrets manager instances, creating fragmentation that undermines centralised control, according to The State of Secrets in AppSec.
  • Only 44% of developers are reported to follow security best practices for secrets management, exposing a significant developer behaviour gap.
  • For the downstream controls that matter after CLI login, see Ultimate Guide to NHIs , 2025 Outlook and Predictions for the lifecycle and governance angle.

What this signals

Browser-mediated CLI login is becoming a governance boundary, not just a UX choice. As more tools adopt device-code authentication, teams need to define where human consent ends and token lifecycle control begins. The operational risk is not the browser step itself, but the uncontrolled reuse of the token that comes after it.

Token fragmentation is the hidden failure mode in terminal workflows. When CLI sessions create credentials that are stored differently across users, hosts, and tools, policy enforcement becomes inconsistent. The average of 6 distinct secrets manager instances cited in our secrets research shows why distributed storage models make central review harder, not easier.

If your programme is adopting device-code login for internal tooling, align it with NIST SP 800-63 Digital Identity Guidelines for authentication assurance and with explicit token retention rules. The next maturity step is not more login convenience, but clearer control over where issued credentials can live and how long they remain usable.


For practitioners

  • Define token storage boundaries Store device-flow access tokens in the smallest practical local scope, avoid writing them to logs or shell history, and set explicit expiration and revocation handling for CLI sessions. The browser approval step does not remove the need to protect the issued credential.
  • Enforce server-driven polling behaviour Use the interval returned by the authorization response, handle slow_down by backing off, and stop polling cleanly when the code expires or is denied. This keeps the CLI aligned with the auth server instead of creating avoidable pressure or ambiguous failure states.
  • Separate user approval from credential reuse Treat browser consent as authentication, then require a distinct policy for how the CLI stores and reuses the resulting access token for API calls. That policy should define where the token lives, when it is refreshed, and how it is revoked.
  • Audit CLI login paths for secret leakage Review stdout, debug logs, telemetry, and crash reports for accidental token exposure, and block any code path that prints bearer tokens or refresh tokens. In a terminal workflow, accidental disclosure is often the fastest path from convenience to compromise.

Key takeaways

  • Python CLI device-code login improves usability, but it shifts the security problem into token lifecycle control after browser approval.
  • The main governance risk is not the terminal prompt itself, but careless storage, logging, or reuse of the access token that the CLI receives.
  • Teams should pair server-correct polling with strict local secret handling so that delegated authentication does not become credential exposure.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

NIST SP 800-63, NIST CSF 2.0 and NIST Zero Trust (SP 800-207) set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
NIST SP 800-63Device-code login is an authentication pattern covered by digital identity guidance.
NIST CSF 2.0PR.AC-1The article centers on controlled access and authenticated use of CLI tools.
NIST Zero Trust (SP 800-207)PR.AC-4Token issuance after approval fits continuous access and least-privilege thinking.

Use 800-63-aligned assurance and session controls for browser-mediated CLI authentication.


Key terms

  • Device Authorization Grant: An OAuth 2.0 flow designed for devices or clients that cannot easily present a browser during login. The user completes authentication in a separate browser session, while the client polls for authorization and then receives tokens tied to that approved session.
  • Bearer Token: A credential that grants access to an API or service to whoever possesses it. In CLI workflows, a bearer token can be powerful and fragile at the same time, because accidental exposure in logs, files, or telemetry can immediately expand the blast radius.
  • Token Lifecycle: The full set of controls that govern how an issued token is stored, refreshed, revoked, and retired. For CLI tools, lifecycle discipline matters because authentication ends at approval, but access continues through the token until it expires or is explicitly invalidated.

Deepen your knowledge

Python CLI device-code authentication and token lifecycle control are covered in our NHI Foundation Level course, the industry's only accredited NHI security programme. If you are building CLI login into developer tooling or internal automation, it is a practical place to start.

This post draws on content published by WorkOS: How to add auth to your Python CLI using WorkOS Authenticate users in your Python command-line tool with a secure OAuth 2.0 Device Code flow. Read the original.

NHIMG Editorial Note
Published by the NHIMG editorial team on 2025-07-25.
NHI Mgmt Group — the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org