Uh oh!
There was an error while loading. Please reload this page.
feat(cli): authenticate with Bearer + verify token on login (cli#83) - #86
Merged
shujaatTracebloc merged 2 commits intoJun 18, 2026
Merged
Conversation
Completes `tracebloc login` against the now-built device-grant endpoints
(backend#846). The token the flow issues is a ClientAccessToken, which the
backend authenticates as `Authorization: Bearer` (ClientAccessTokenAuthentication,
backend#835) — not the legacy DRF `Token` scheme the client was sending on
authenticated requests, which would have failed to authenticate a logged-in token.
- internal/api: authenticated requests now send `Bearer <token>` (was `Token`);
add get() + WhoAmI() (GET /userinfo/) to confirm the token + fetch the account.
- login now verifies the freshly-issued token (best-effort) and stores/shows the
account ("Signed in as you@co.com"); a failed lookup never fails a valid sign-in.
- tests: WhoAmI sends Bearer + parses the identity; a 401 surfaces as an APIError.
The device-flow contract (paths/fields/error codes) was already aligned with
backend#846 — verified, unchanged. Stacked on cli#85 (auth scaffold).
go build/vet/test green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>LukasWodka
commented
Jun 18, 2026
ContributorAuthor
👋 Heads-up — Code review queue is at 38 / 30 Above the WIP limit. The team convention is to review existing PRs before opening new work. Open PRs currently in Code review (oldest first):
Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.) |
internal/api was unit-tested, but the login / logout / auth status COMMANDS weren't. Adds auth_test.go driving the full device-flow command against an httptest backend whose shapes match backend#846 — so it also guards the CLI<->backend contract that the Token->Bearer fix corrected: - login: device_code -> authorization_pending -> token -> WhoAmI(Bearer) -> "Signed in as ..." with config persisted; the 404 "unsupported backend" gate (asserts no token is stored); access_denied. - logout clears the token; auth status (signed-in + not-signed-in). Two unexported test seams in auth.go — newAPIClient (point at an httptest server) and pollAfter (fire the poll immediately) — since the flow otherwise makes real HTTP calls on a timer. go build / vet / test green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
shujaatTracebloc
approved these changes
Jun 18, 2026
Uh oh!
There was an error while loading. Please reload this page.
shujaatTracebloc pushed a commit
that referenced
this pull request
Jun 19, 2026
…d client (cli#83) (#85) * feat(cli): auth scaffold — login/logout/auth status + config + backend client (cli#83) RFC-0001 (backend#830) Phase-1 CLI side, scaffolded ahead of the backend device-grant so it activates the moment backend#835 ships. - internal/config: ~/.tracebloc config store (0600, atomic write) — backend env + user token + active client. Fully functional + unit-tested. - internal/api: backend REST client. CLIENT_ENV -> {dev,stg,prod} base URL (matches the installer's _backend_url); proxy + CA aware (honors HTTP(S)_PROXY / NO_PROXY + the system cert pool, for corporate-proxy networks); the RFC 8628 device-flow methods (RequestDeviceCode + PollToken with the authorization_pending / slow_down / expired_token / access_denied states). Unit-tested via httptest. - internal/cli: `tracebloc login` (device flow — show URL + code, poll, store the token), `logout`, `auth status`. `client create/list/use` are stubbed (cli#84 — they need the user token from login + provisioning backend#836). login calls /device/code + /device/token, which land in backend#835; until then it reports that the backend doesn't support browser sign-in yet. Builds, gofmt-clean, unit-tested (config round-trip + 0600 mode; api URL map + device-flow poll states); `tracebloc --help` lists the new verbs. Part of cli#83 / backend#830 (end-to-end login activates with backend#835). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(cli): authenticate with Bearer + verify token on login (cli#83) (#86) * feat(cli): authenticate with Bearer + verify token on login (cli#83) Completes `tracebloc login` against the now-built device-grant endpoints (backend#846). The token the flow issues is a ClientAccessToken, which the backend authenticates as `Authorization: Bearer` (ClientAccessTokenAuthentication, backend#835) — not the legacy DRF `Token` scheme the client was sending on authenticated requests, which would have failed to authenticate a logged-in token. - internal/api: authenticated requests now send `Bearer <token>` (was `Token`); add get() + WhoAmI() (GET /userinfo/) to confirm the token + fetch the account. - login now verifies the freshly-issued token (best-effort) and stores/shows the account ("Signed in as you@co.com"); a failed lookup never fails a valid sign-in. - tests: WhoAmI sends Bearer + parses the identity; a 401 surfaces as an APIError. The device-flow contract (paths/fields/error codes) was already aligned with backend#846 — verified, unchanged. Stacked on cli#85 (auth scaffold). go build/vet/test green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(cli): cover the login command end-to-end + add test seams (cli#83) internal/api was unit-tested, but the login / logout / auth status COMMANDS weren't. Adds auth_test.go driving the full device-flow command against an httptest backend whose shapes match backend#846 — so it also guards the CLI<->backend contract that the Token->Bearer fix corrected: - login: device_code -> authorization_pending -> token -> WhoAmI(Bearer) -> "Signed in as ..." with config persisted; the 404 "unsupported backend" gate (asserts no token is stored); access_denied. - logout clears the token; auth status (signed-in + not-signed-in). Two unexported test seams in auth.go — newAPIClient (point at an httptest server) and pollAfter (fire the poll immediately) — since the flow otherwise makes real HTTP calls on a timer. go build / vet / test green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Completes
tracebloc loginnow that the backend device-grant endpoints exist (backend#846), and fixes a credential-scheme mismatch.The fix
The device flow issues a
ClientAccessToken, which the backend authenticates asAuthorization: **Bearer** <token>(ClientAccessTokenAuthentication, backend#835). The client was sendingAuthorization: **Token** <token>(the legacy DRF scheme) on authenticated requests — so a logged-in token would have failed to authenticate. Switched toBearer.Changes
internal/api—setAuthnow sendsBearer <token>(wasToken); addedget()+WhoAmI()(GET/userinfo/, the backend's "user from token" endpoint) to confirm the token is live and return the account.login— after storing the token, verifies it against the backend (best-effort) and stores/shows the account:Signed in as you@co.com. A failed verify never fails an otherwise-successful sign-in (offline, or a backend without PR1 deployed yet).WhoAmIsendsBearer+ parses the identity; a 401 surfaces as anAPIError.The device-flow contract (paths
/device/code+/device/token, field names, theauthorization_pending/slow_down/access_denied/expired_tokencodes) was already aligned with backend#846 — verified, no change needed. The "backend doesn't support browser login yet" guard stays as a graceful fallback for older backends.Test plan
Full CLI↔live-backend e2e awaits backend#846 + #835 deploying; verified here against httptest mocks matching the #846 contract.
🤖 Generated with Claude Code