feat: OAuth browser login with automatic token lifecycle (0.3.1)#93
feat: OAuth browser login with automatic token lifecycle (0.3.1)#93Episkey-G wants to merge 8 commits into
Conversation
Add 'ucloud auth login' / 'ucloud auth logout' implementing OAuth 2.0 authorization-code flow with RFC 8252 loopback auto-capture of the callback (--no-browser prints the URL and falls back to manual paste). auth_mode on the profile picks exactly one credential mechanism per request: oauth profiles send Authorization: Bearer only (stored AK/SK stay inert for logout restore), AK/SK and CloudShell signing paths are byte-identical to before. Token lifecycle is fully automatic: proactive refresh before expiry (5-minute clock-skew margin), reactive refresh-and-replay-once when the gateway rejects a token mid-command (RetCode 174), refresh rotation serialized across processes with a file lock plus reread-after-lock, and credential/config files written atomically (temp+fsync+rename). Token values are redacted across all log sinks and the panic path. Also fixes: config update --base-url validated against the old gateway (chicken-and-egg), login kept a stale project_id from another account, init on an oauth profile did not persist the switch back to AK/SK, /dev/null was misdetected as an interactive terminal, and AggConfigManager held process-lifetime file handles that break os.Rename on Windows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…arning; redact oauth error desc Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Self-review follow-ups addressed in the latest push:
All gates re-run green: full 🤖 Generated with Claude Code |
… base/endpoints.go Move the API gateway base URL, OAuth base URL, client credentials, scope, /authorize and /token endpoint paths, and the loopback callback constants into one file grouped by service domain. The callback path is now a single exported constant (base.OAuthRedirectPath) shared by the redirect_uri builder and the callback server's mux, removing a cross-file duplicate that had to be kept in sync by hand. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Follow-up: centralized all service URLs, hosts and endpoint paths into a new 🤖 Generated with Claude Code |
…r defaults DefaultBaseURL belongs with the other profile-default constants; a dedicated file separated it from its peers. Keep the overridable default URLs together (api gateway + oauth) and group the OAuth protocol/loopback constants in config.go. No behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…bal flag Mirror --base-url: add --oauth-base-url to config add/update, a global --oauth-base-url override, and the GlobalFlag/mergeConfigIns plumbing so oauth_base_url can be configured without hand-editing config.json — needed for environments whose OAuth domain differs from the default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Two more follow-ups pushed:
Pure-structure change (1) and new-flag change (2, TDD). Full ./base + ./cmd tests and the matrix (8/8) stay green; 🤖 Generated with Claude Code |
…-domain login A new user targeting a non-default OAuth environment was stuck: the global --oauth-base-url is not accepted on the auth command group, config update needs an existing profile, and config add requires AK/SK. auth login now takes its own --oauth-base-url, usable with no prior config and persisted to the profile so later refreshes reuse it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Added 🤖 Generated with Claude Code |
Summary
Adds browser-based OAuth login to ucloud-cli, so interactive users no longer need to handle AK/SK keys:
ucloud auth login— opens the UCloud authorization page; the callback is captured automatically via an RFC 8252 loopback server on 127.0.0.1 (no copy-paste).--no-browserprints the URL for SSH/headless use and falls back to manual paste, as does a 3-minute capture timeout.ucloud auth logout— removes local tokens only; stored AK/SK keys are kept and restored.Credential model
auth_modeon a profile selects exactly one credential mechanism per request:Authorization: Beareronly — signature parameters are never emitted.--public-key/--private-keyflags still take precedence and use signing.ucloud auth loginrefuses non-interactive terminals with a pointer to AK/SK).Token lifecycle (fully automatic)
Robustness / security
config listshows anAuthModecolumn and never prints tokens.HTTPS_PROXY/HTTP_PROXY/NO_PROXY(pinned by test).config update --base-urlvalidated against the old gateway (impossible to recover from a wrong base-url);initon an OAuth profile didn't persist the switch back to AK/SK;/dev/nullstdin was misdetected as an interactive terminal; AggConfigManager held process-lifetime file handles that would breakos.Renameon Windows.Testing
./base/suite incl. concurrency tests under-race(single rotation under concurrent refresh, replay-once guarantees, negative paths).tests/oauth_cli_matrix.sh, sandbox HOME): non-TTY fail-fast, missing-token guidance, logout idempotence, OAuth/AK-SK profile coexistence, init switch-back persistence — 8/8.Notes for reviewers
statecheck and loopback redirect.vendor/adds github.com/gofrs/flock v0.8.1 (file locking).🤖 Generated with Claude Code