TL;DR: CLI authentication to enterprise SSO works best when teams choose between OAuth Device Code and PKCE based on runtime context, not convenience, according to WorkOS. The broader lesson is that headless and local environments need different identity patterns, and refresh-token storage becomes the control point that matters most.
NHIMG editorial — based on content published by WorkOS: How to add enterprise SSO to your CLI
By the numbers:
- A 0600 file is portable, has no native dependencies, and works in containers, WSL, and CI runners that do not have a keyring service running.
- AWS CLI v2 writes SSO tokens as 0600-permissioned JSON files in ~/.aws/sso/cache/.
Questions worth separating out
Q: How should security teams choose between Device Code and PKCE for CLI sign-in?
A: Use PKCE when the user has a local browser and the CLI can bind to a loopback redirect.
Q: Why do CLI refresh tokens need stronger protection than access tokens?
A: Refresh tokens matter more because they last longer and can mint new access tokens after the short-lived access token expires.
Q: What breaks when a CLI relies on a single login flow for every environment?
A: A single flow usually fails either in headless environments, where loopback browser redirection is unavailable, or on local machines, where Device Code adds a manual transfer step and a polling window.
Practitioner guidance
- Default CLI sign-in to PKCE where a browser callback exists Use the loopback redirect pattern for local developer machines and keep Device Code only for SSH, containers, and other headless environments where callback handling is impossible.
- Treat refresh tokens as the durable credential asset Store them in a permission-restricted location or OS keychain, and replace the stored value whenever the refresh response rotates the token pair.
- Keep the device code secret out of user-facing output Show only the user code and verification URL, because the device_code is the private half of the pair and should never be displayed in the terminal.
What's in the full article
WorkOS's full tutorial covers the operational detail this post intentionally leaves for the source:
- Complete TypeScript implementation for both Device Code and PKCE CLI login paths.
- Exact WorkOS dashboard configuration steps for application setup, redirect URIs, and Okta SSO.
- Token refresh code, loopback server handling, and the sample CLI command wiring.
- Practical notes on browser opening, polling behaviour, and session persistence choices.
👉 Read WorkOS's tutorial on adding enterprise SSO to a CLI →
CLI SSO flows: what changes for headless and local auth?
Explore further
CLI SSO is now an identity governance problem, not a developer ergonomics problem. The article shows that terminal-based tools must inherit enterprise SSO controls rather than bypass them with static secrets. That matters because the security review question is no longer whether the CLI can authenticate, but whether it can participate in the organisation's existing identity policy stack. For practitioners, the right lens is whether the command-line workload can be brought under the same governance model as web and internal apps.
A few things that frame the scale:
- Only 1.5 out of 10 organisations are highly confident in their ability to secure NHIs, compared to nearly 1 in 4 for securing human identities, according to the State of Non-Human Identity Security.
- 85% of organisations lack full visibility into third-party vendors connected via OAuth apps, with 38% reporting no or low visibility and 47% reporting only partial visibility.
A question worth separating out:
Q: Who is accountable for CLI session security when tokens are stored locally?
A: The application team is accountable for the storage model, expiry handling, and revocation path, while the identity team is accountable for enforcing the enterprise authentication policy behind the flow. In practice, that means CLI design has to align with access governance rather than being treated as a standalone developer convenience.
👉 Read our full editorial: Enterprise SSO for CLIs depends on the right OAuth flow