Subscribe to the Non-Human & AI Identity Journal

How should security teams choose between Device Code and PKCE for CLI sign-in?

Use PKCE when the user has a local browser and the CLI can bind to a loopback redirect. Use Device Code when the environment is headless, remote, or browserless. The deciding factor is not preference but whether the runtime can preserve a browser-tied authorization path without adding unnecessary phishing or polling exposure.

Why This Matters for Security Teams

Device Code and PKCE are not interchangeable UX choices. They shape where trust is anchored, how much phishing exposure exists, and whether a CLI can bind authentication to the device that actually initiated the sign-in. For security teams, the real decision is whether the runtime can safely complete a browser-tied authorization flow or whether it must rely on a separate device and user code path.

This matters because CLIs often run in environments that are more variable than browser apps: laptops, jump hosts, remote shells, ephemeral build agents, and locked-down containers. A poor default can create avoidable risk, especially when secrets are copied between terminals or when users are trained into approving codes they do not fully understand. NIST guidance on identity assurance and access control supports choosing the least risky flow for the context, not the most convenient one, as reflected in the NIST Cybersecurity Framework 2.0.

NHI Management Group’s Ultimate Guide to NHIs highlights how frequently identity failures stem from weak lifecycle controls and poor visibility, which is relevant here because CLI auth mistakes often become durable credential problems rather than one-time login issues. In practice, many security teams encounter token theft, code reuse, or confused-deputy sign-ins only after a tool has already been widely adopted.

How It Works in Practice

PKCE is generally the stronger choice when a CLI can open or bind to a local browser session on the same device. The loopback redirect lets the application receive the authorization response locally, while PKCE binds the authorization code to the initiating client. That lowers the chance that a stolen code can be replayed elsewhere, and it aligns well with desktop workflows where the user and device are both present.

Device Code is the practical fallback for headless, remote, or browserless environments. Instead of forcing a local browser redirect, the CLI displays a short code and the user completes sign-in on a separate trusted browser. That makes it usable from SSH sessions, container shells, and automation entry points where loopback redirects are not possible.

Security teams usually evaluate the two flows against a few operational questions:

  • Can the CLI securely launch or receive a local redirect on the same device?
  • Is the environment interactive, or is it remote, headless, or ephemeral?
  • Would user-code entry create avoidable phishing or support risk in this workflow?
  • Can the client store tokens safely after sign-in, or will it leak them into logs and shell history?

For implementation, PKCE should be paired with short-lived tokens, tight redirect URI handling, and explicit loopback-only behavior. Device Code should be used with careful polling limits, clear user education, and strict validation that the browser session is really tied to the intended login. Current guidance suggests treating Device Code as a usability bridge, not a general-purpose default. The identity lifecycle concerns described in Ultimate Guide to NHIs become especially relevant when CLI tokens are reused across jobs or cached on shared systems.

These controls tend to break down when CLIs are embedded inside CI/CD runners or remote automation hosts because the sign-in context is no longer clearly owned by one human session.

Common Variations and Edge Cases

Tighter sign-in controls often increase friction, requiring organisations to balance phishing resistance against developer throughput. That tradeoff becomes visible in shared admin tooling, first-run onboarding, and support workflows where a browser may exist but cannot be safely bound to the local process.

There is no universal standard for this yet, but current best practice is to prefer PKCE wherever the client can complete a local loopback flow, and reserve Device Code for situations where that is not possible. Some teams also standardise on Device Code for all CLIs to simplify support, but that can widen the window for code interception or encourage insecure copy-and-paste habits. Others try to force PKCE into remote shells, which usually fails operationally and pushes users toward workarounds.

Edge cases include browser launches blocked by endpoint policy, terminals inside VDI environments, and developer tooling that spawns multiple child processes. In those environments, the deciding factor is not abstract security preference but whether the auth path remains bound to the initiating runtime. When that binding is weak or absent, Device Code can be acceptable if the surrounding controls are strong. When the binding is available, PKCE is typically the safer default.

For program owners, the practical rule is to document which flow is approved for each runtime class and to review token storage, refresh behaviour, and revocation handling alongside the sign-in method itself. The wrong choice is usually discovered after support tickets, not during design.

Standards & Framework Alignment

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

OWASP Agentic AI Top 10 and OWASP Non-Human Identity Top 10 address the attack and risk surface, while NIST CSF 2.0 set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
OWASP Agentic AI Top 10 A1 Auth flow choice must resist token theft and phishing in tool-driven runtimes.
OWASP Non-Human Identity Top 10 NHI-03 CLI tokens are NHI secrets that need rotation and tight lifecycle control.
NIST CSF 2.0 PR.AC-1 Access control should match the runtime context and auth path used by the CLI.

Use short-lived, bound auth flows and avoid reusable credentials in CLI and agent runtimes.