Skip to content

feat(cli): authenticate with Bearer + verify token on login (cli#83) - #86

Merged
shujaatTracebloc merged 2 commits into
feat/rfc-0001-cli-authfrom
feat/835-cli-login-golive
Jun 18, 2026
Merged

feat(cli): authenticate with Bearer + verify token on login (cli#83)#86
shujaatTracebloc merged 2 commits into
feat/rfc-0001-cli-authfrom
feat/835-cli-login-golive

Conversation

@LukasWodka

Copy link
Copy Markdown
Contributor

What

Completes tracebloc login now that the backend device-grant endpoints exist (backend#846), and fixes a credential-scheme mismatch.

Stacked on cli#85 (feat/rfc-0001-cli-auth, the auth scaffold) — base is that branch, so the diff is only these changes. Retarget to develop once #85 merges.

The fix

The device flow issues a ClientAccessToken, which the backend authenticates as Authorization: **Bearer** <token> (ClientAccessTokenAuthentication, backend#835). The client was sending Authorization: **Token** <token> (the legacy DRF scheme) on authenticated requests — so a logged-in token would have failed to authenticate. Switched to Bearer.

Changes

  • internal/apisetAuth now sends Bearer <token> (was Token); added get() + 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).
  • testsWhoAmI sends Bearer + parses the identity; a 401 surfaces as an APIError.

The device-flow contract (paths /device/code + /device/token, field names, the authorization_pending/slow_down/access_denied/expired_token codes) 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

go build ./... # ok
go vet ./internal/... # clean
go test ./internal/api/... ./internal/cli/... # ok (incl. new WhoAmI tests)

Full CLI↔live-backend e2e awaits backend#846 + #835 deploying; verified here against httptest mocks matching the #846 contract.

🤖 Generated with Claude Code

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

Copy link
Copy Markdown
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
shujaatTracebloc merged commit 5914a10 into feat/rfc-0001-cli-authJun 18, 2026
1 check passed
@shujaatTracebloc
shujaatTracebloc deleted the feat/835-cli-login-golive branch June 18, 2026 07:14
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>
Sign up for freeto 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.

3 participants

@LukasWodka@shujaatTracebloc@saadqbal