Skip to content

feat(cli): add lightning login --device for machines without a browser - #218

Merged
lianakoleva merged 1 commit into
mainfrom
vivequeramji/device-code-login
Oct 29, 2026
Merged

lianakoleva merged 1 commit into
mainfrom
vivequeramji/device-code-login

Conversation

@vivequeramji

@vivequeramji vivequeramji commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

lightning login --device signs in on a machine without a browser, such as a remote server or a container, using the OAuth 2.0 device authorization grant (RFC 8628). It prints a short code and an address; the user enters the code in a browser on any other device and approves, and the CLI saves the session the same way lightning login does.

$ lightning login --device
To sign in, open https://lightning.ai/device on any device and enter this code:

    BCDF-GHJK

Waiting for approval. The code expires in 10 minutes.
Successfully logged in as "Alice".

What

  • lightning login --device calls POST /oidc/device_authorization as client lightning-cli, shows the code, and polls POST /oidc/token with the device-code grant at the interval the server gives, adding 5 seconds on slow_down. It stops on access_denied, expired_token, or when expires_in runs out, and saves the session to the usual 0600 credentials file.
  • When the server doesn't offer device login, it says so instead of failing on a raw HTTP error.
  • When lightning login can't open a browser, the error now points at lightning login --device instead of LIGHTNING_API_KEY.
  • README and CLI docs mention --device.

Notes

  • Draft until the platform serves the device endpoints. Until then --device reports that the server doesn't support it.
  • The Go SDK reads the same credentials file, so it picks up a device login with no change.

Tests

pytest tests/cli/utils/test_auth.py tests/cli/test_entrypoint.py: 39 passed. New tests cover polling through authorization_pending and slow_down, denial, expiry reported by the server and by expires_in, a server without device login, and login --device replacing a saved session. ruff check / ruff format --check clean; mypy not run locally.

`lightning login --device` signs in with the OAuth 2.0 device authorization
grant (RFC 8628): it prints a code to enter in a browser on any other device,
polls until the sign-in is approved, and saves the session the same way
`lightning login` does. When `lightning login` can't open a browser, its error
now points at `--device`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@ethanwharris ethanwharris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! My only question is whether --device is the right flag, is that standard? Or are other things doing like --no-browser or something?

@vivequeramji

Copy link
Copy Markdown
Contributor Author

Nice! My only question is whether --device is the right flag, is that standard? Or are other things doing like --no-browser or something?

This still requires to input the code on a browser so I think that would be a misnomer here.

Cloudflare: wrangler login --device
GitHub: gh auth login --web
Azure: az login --use-device-code
AWS: aws sso login --use-device-code

@dhedey dhedey left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dhedey dhedey left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the fallback I'd suggest going with paste-back (auth code + PKCE, like gcloud auth login --no-launch-browser or claude code's no browser path) over the device flow.

Most companies are slowly looking to drop device flow because it's a little too easy to convince someone to enter a code at a URL:

  • gcloud dropped device code a few years ago
  • AWS swapped their default to Auth code + PKCE since CLI 2.22.0

Claude pipes in with:

The Device Code RFC is from 2019, but the newer guidance is blunter - RFC 10027 (BCP 247, 2026) says to use it only if nothing else is viable, and to "avoid using if the protected resources are sensitive, high value, or business critical."

Paste-back is a little better - it's the same auth code + PKCE flow we already use, with a page that shows the code in place of the localhost redirect. To phish it, someone has to be talked into sending the code to the attacker, and a code leaked any other way is useless without the PKCE verifier.

The page should also make very clear what access pasting back provides -- i.e. "This gives access to your account. Only paste it back into a CLI or SDK that you trust. Do not give it to anyone else" style of message.


Alternatively, if we want to keep device code, we could reduce the risk of phishing a little by making very clear in the UI before entering the code that by entering a code, you are authorizing the thing that gave you the code full access to your account, before showing them the box to enter the code.

Happy with either, I just want to make sure we're responsible with how we do things :)

@vivequeramji

Copy link
Copy Markdown
Contributor Author

For the fallback I'd suggest going with paste-back (auth code + PKCE, like gcloud auth login --no-launch-browser or claude code's no browser path) over the device flow.

Most companies are slowly looking to drop device flow because it's a little too easy to convince someone to enter a code at a URL:

  • gcloud dropped device code a few years ago
  • AWS swapped their default to Auth code + PKCE since CLI 2.22.0

Claude pipes in with:

The Device Code RFC is from 2019, but the newer guidance is blunter - RFC 10027 (BCP 247, 2026) says to use it only if nothing else is viable, and to "avoid using if the protected resources are sensitive, high value, or business critical."

Paste-back is a little better - it's the same auth code + PKCE flow we already use, with a page that shows the code in place of the localhost redirect. To phish it, someone has to be talked into sending the code to the attacker, and a code leaked any other way is useless without the PKCE verifier.

The page should also make very clear what access pasting back provides -- i.e. "This gives access to your account. Only paste it back into a CLI or SDK that you trust. Do not give it to anyone else" style of message.

Alternatively, if we want to keep device code, we could reduce the risk of phishing a little by making very clear in the UI before entering the code that by entering a code, you are authorizing the thing that gave you the code full access to your account, before showing them the box to enter the code.

Happy with either, I just want to make sure we're responsible with how we do things :)

Interesting, yeah paste-back seems to be better. Let me make a plan for these changes, but in the meantime we can add the device flow since this is ready. We already have the UI in place to have an explicit approve and deny https://github.com/gridai/grid/pull/49150

@lianakoleva
lianakoleva merged commit 334c0cb into main Oct 29, 2026
38 checks passed
@lianakoleva
lianakoleva deleted the vivequeramji/device-code-login branch October 29, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants