Token-based auth — bearer + refresh-token flow for native clients #180

Closed
opened 2026-06-20 15:44:01 +00:00 by james · 0 comments
Owner

Extend the existing cookie-session auth to also issue bearer tokens with refresh rotation, so the native (Android, Linux Flatpak) clients can authenticate against a self-hoster's deployment.

The web Expo build keeps the existing same-origin cookie flow. Native gets bearer tokens stored in secure storage. ADR-0015 (OAuth2 + linking) and ADR-0004 (server-side sessions) both stay — this ticket layers tokens on top.

Scope

  • Issue access tokens (short-lived; recommend opaque + DB-backed, consistent with ADR-0004's server-side-sessions philosophy) and refresh tokens (long-lived, rotating on each use).
  • Mint endpoint: POST /api/auth/token accepting local credentials or an OAuth2 callback.
  • Refresh endpoint: POST /api/auth/refresh with rotation and reuse detection — a refresh token used twice revokes the whole token family.
  • Add Authorization: Bearer <token> as an accepted credential alongside the session cookie. The session layer resolves either to the same User.
  • Document the token storage requirement for native (Expo's SecureStore); reference it in the Expo scaffolding ticket.
  • Extend the OpenAPI security schemes with bearerAuth.

Acceptance criteria

  • POST /api/auth/token and POST /api/auth/refresh exist, are zod-typed, and round-trip on both DB engines.
  • A bearer-authenticated request resolves to the same User and is subject to identical per-user isolation as a cookie-authenticated one.
  • Refresh-token reuse triggers a family revocation (testable end-to-end).
  • OpenAPI security schemes document both cookieAuth and bearerAuth.
  • CLAUDE.md "Auth model is strict" reflects the new shape; ADR-0027 references this work.

Out of scope

  • Personal Access Tokens for MCP / external agents (#47, ADR-0021) — orthogonal.
  • Native secure-storage wiring on the client side (Expo scaffolding ticket).

Composes with

ADR-0004, ADR-0015, ADR-0021, Expo client scaffolding, OpenAPI spec generation.

Part of

#176

Extend the existing cookie-session auth to also issue **bearer tokens with refresh rotation**, so the native (Android, Linux Flatpak) clients can authenticate against a self-hoster's deployment. The web Expo build keeps the existing same-origin cookie flow. Native gets bearer tokens stored in secure storage. ADR-0015 (OAuth2 + linking) and ADR-0004 (server-side sessions) both stay — this ticket layers tokens on top. ## Scope - Issue access tokens (short-lived; recommend opaque + DB-backed, consistent with ADR-0004's server-side-sessions philosophy) and refresh tokens (long-lived, rotating on each use). - Mint endpoint: `POST /api/auth/token` accepting local credentials or an OAuth2 callback. - Refresh endpoint: `POST /api/auth/refresh` with rotation and **reuse detection** — a refresh token used twice revokes the whole token family. - Add `Authorization: Bearer <token>` as an accepted credential alongside the session cookie. The session layer resolves either to the same `User`. - Document the token storage requirement for native (Expo's `SecureStore`); reference it in the Expo scaffolding ticket. - Extend the OpenAPI security schemes with `bearerAuth`. ## Acceptance criteria - [ ] `POST /api/auth/token` and `POST /api/auth/refresh` exist, are zod-typed, and round-trip on both DB engines. - [ ] A bearer-authenticated request resolves to the same `User` and is subject to identical per-user isolation as a cookie-authenticated one. - [ ] Refresh-token reuse triggers a family revocation (testable end-to-end). - [ ] OpenAPI security schemes document both `cookieAuth` and `bearerAuth`. - [ ] CLAUDE.md "Auth model is strict" reflects the new shape; ADR-0027 references this work. ## Out of scope - Personal Access Tokens for MCP / external agents (#47, ADR-0021) — orthogonal. - Native secure-storage wiring on the client side (Expo scaffolding ticket). ## Composes with ADR-0004, ADR-0015, ADR-0021, Expo client scaffolding, OpenAPI spec generation. ## Part of #176
james closed this issue 2026-06-21 02:21:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
james/carol#180
No description provided.