You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The brev login --token $TOKEN flow is the path agents and scripts use (the snippet copy-pasted from https://brev.nvidia.com/settings/cli). Today the token served by that page is, in practice, a raw access JWT. Because it has no accompanying refresh material, the resulting CLI session expires roughly every time NVIDIA KAS rolls the access token — which is often within the hour — and the user is forced to re-run brev login --token from scratch.
This issue tracks the backend / frontend change required to give that flow a refreshable credential. The CLI-side workaround (stop writing a bogus "auto-login" refresh token and add 401 retry) is already in #359, but that PR cannot extend session lifetime on its own — the CLI has nothing to refresh with.
How the interactive brev login flow already solves this
pkg/auth/kas.goDoDeviceAuthFlow (interactive browser login) does the following:
Generates a random deviceID (UUID) and POSTs to /device/login with the user's email.
KAS returns a sessionKey.
The user completes SSO in the browser.
The CLI polls /token with Authorization: Bearer $sessionKey and x-device-id: $deviceID until it gets a signed ID token.
The CLI stores AccessToken = idToken, RefreshToken = "$sessionKey:$deviceID".
The sessionKey:deviceID pair is already a working refresh credential — KasAuthenticator.GetNewAuthTokensWithRefresh re-calls /token whenever the access JWT expires, and the session key itself is good for up to 24 hours (see comment at pkg/auth/kas.go:207).
So the refresh machinery on the CLI side and on the KAS side is already in place. The --token path just isn't using it.
Option A (preferred, smallest server change): serve the sessionKey:deviceID pair directly.
Server-side: mint a sessionKey bound to a freshly-generated deviceID (same shape as the interactive device flow produces) and show the string sessionKey:deviceID as the --token value in the copy/paste snippet.
Client-side: no changes required.LoginWithToken already has an else branch that correctly treats a non-JWT input as a refresh token and drives the first API call through the refresh path.
Result: brev login --token $TOKEN produces a 24-hour CLI session that auto-renews its access JWT every time it expires, matching the UX of the interactive browser flow.
Option B (slightly larger, more extensible): serve a base64-encoded JSON blob like {"refresh_token": "sessionKey:deviceID", "version": 1}.
Gives future headroom to pass additional metadata (e.g. token expiry, scopes, CLI-friendly capabilities) without another format change.
Requires a small CLI-side change: detect the base64/JSON envelope in LoginWithToken and unpack it before handing to the refresh path. Backward-compatible — old plain-string tokens still work.
Option C (largest, most durable): introduce a CLI-scoped PAT-style token.
Server-side: new endpoint that issues a long-lived (30–90 day) rotating refresh token scoped to CLI use, separate from the 24-hour KAS sessionKey.
Client-side: CLI saves {access_token, refresh_token, refresh_token_exp} and rotates on each refresh.
Best UX for agents / long-running automation; largest coordination cost.
Recommendation
Ship Option A first. It's the smallest change that solves the reported user pain ("I get logged out multiple times per hour"), it reuses the refresh path that the interactive flow has relied on for a long time, and it requires no CLI release — users benefit as soon as the webpage is updated.
Option C remains worth doing later for truly long-lived automation, but it's not a prerequisite for fixing the immediate logout problem.
Verifying the current behavior
To confirm the webpage is currently handing out a raw JWT (not a sessionKey:deviceID):
Summary
The
brev login --token $TOKENflow is the path agents and scripts use (the snippet copy-pasted from https://brev.nvidia.com/settings/cli). Today the token served by that page is, in practice, a raw access JWT. Because it has no accompanying refresh material, the resulting CLI session expires roughly every time NVIDIA KAS rolls the access token — which is often within the hour — and the user is forced to re-runbrev login --tokenfrom scratch.This issue tracks the backend / frontend change required to give that flow a refreshable credential. The CLI-side workaround (stop writing a bogus
"auto-login"refresh token and add 401 retry) is already in #359, but that PR cannot extend session lifetime on its own — the CLI has nothing to refresh with.How the interactive
brev loginflow already solves thispkg/auth/kas.goDoDeviceAuthFlow(interactive browser login) does the following:deviceID(UUID) and POSTs to/device/loginwith the user's email.sessionKey./tokenwithAuthorization: Bearer $sessionKeyandx-device-id: $deviceIDuntil it gets a signed ID token.AccessToken = idToken,RefreshToken = "$sessionKey:$deviceID".The
sessionKey:deviceIDpair is already a working refresh credential —KasAuthenticator.GetNewAuthTokensWithRefreshre-calls/tokenwhenever the access JWT expires, and the session key itself is good for up to 24 hours (see comment atpkg/auth/kas.go:207).So the refresh machinery on the CLI side and on the KAS side is already in place. The
--tokenpath just isn't using it.What needs to change
The page at https://brev.nvidia.com/settings/cli should issue a refresh credential, not a raw access JWT. Two options, smallest first:
Option A (preferred, smallest server change): serve the
sessionKey:deviceIDpair directly.sessionKeybound to a freshly-generateddeviceID(same shape as the interactive device flow produces) and show the stringsessionKey:deviceIDas the--tokenvalue in the copy/paste snippet.LoginWithTokenalready has an else branch that correctly treats a non-JWT input as a refresh token and drives the first API call through the refresh path.brev login --token $TOKENproduces a 24-hour CLI session that auto-renews its access JWT every time it expires, matching the UX of the interactive browser flow.Option B (slightly larger, more extensible): serve a base64-encoded JSON blob like
{"refresh_token": "sessionKey:deviceID", "version": 1}.LoginWithTokenand unpack it before handing to the refresh path. Backward-compatible — old plain-string tokens still work.Option C (largest, most durable): introduce a CLI-scoped PAT-style token.
{access_token, refresh_token, refresh_token_exp}and rotates on each refresh.Recommendation
Ship Option A first. It's the smallest change that solves the reported user pain ("I get logged out multiple times per hour"), it reuses the refresh path that the interactive flow has relied on for a long time, and it requires no CLI release — users benefit as soon as the webpage is updated.
Option C remains worth doing later for truly long-lived automation, but it's not a prerequisite for fixing the immediate logout problem.
Verifying the current behavior
To confirm the webpage is currently handing out a raw JWT (not a
sessionKey:deviceID):brev login --token $TOKENsnippet from https://brev.nvidia.com/settings/cli.$TOKEN— if it has three base64 segments separated by., it's a JWT.pkg/auth/auth.goLoginWithToken: a JWT input takes theif validbranch (which is the broken path fixed in fix(auth): refresh on 401 and stop writing bogus refresh tokens #359), while asessionKey:deviceIDinput takes theelsebranch (the working path).Out of scope for this issue
🤖 Generated with Claude Code