Blog

Why a CLI should never ask for your password

The device flow lets a command-line tool sign in without ever seeing a credential. Here is how it works, and the one way it gets phished.

The problem with typing a password into a terminal

A command-line tool that prompts for a password has to be trusted with it. The password passes through the tool’s process, perhaps a shell history file, perhaps a log. Two-factor prompts make it worse, not better: now the tool has to proxy those too.

The alternative people reach for is pasting a long-lived API key into a config file. That trades one problem for another — the key never expires, belongs to no particular machine, and gets copied to every laptop that needs it.

How the device flow works

The CLI asks the server to start a login and receives two codes: a long secret one it keeps, and a short one it shows you. You open a browser, where you are already signed in, and approve the short code. Meanwhile the CLI polls with the secret code; once you approve, the poll returns a token.

The credential never touches the terminal. The browser session does the authenticating, with whatever second factor your identity provider demands, and the CLI only ever holds a token scoped to that one machine.

The one way it gets phished

The weakness is that approving a code is easy. An attacker starts a login on their own machine and sends you the link. If you approve it, their machine is now signed in as you.

The defence is context. An approval page should show what the server actually saw — the IP address and client that started the request, and when — so a login you did not start looks like one. A device name alone is not enough: the requester chose it.

Why per-device tokens matter afterwards

Because each machine gets its own token, losing a laptop is a one-click problem: revoke that device, and nothing else changes. No secret needs rotating, and no other machine needs signing in again.

Store only a hash of each token on the server, expire the ones that sit unused, and a leaked database yields nothing that can be replayed.

← All articles