Skip to content

Conversation

@hammadtq
Copy link
Contributor

Summary

  • Adds Bearer token authentication (Authorization: Bearer oba_...) to the registry-service so CLIs/agents can call authenticated endpoints (keys, agents, profiles) without a browser session
  • Token management endpoints (create/list/revoke) remain session-cookie-only to prevent token-bootstrap attacks
  • Includes DB migration, rate limiting, and 28 unit tests

What changed

New files:

  • infra/neon/migrations/005_api_tokens.sqlapi_tokens table with SHA-256 hash index
  • src/middleware/token-auth.ts — Bearer token middleware that populates req.session transparently
  • src/middleware/rate-limit.ts — Reusable in-memory rate limiter factory
  • src/routes/tokens.ts — POST (create, 201), GET (list), DELETE (revoke) endpoints
  • src/utils/crypto.tshashToken utility (isolated from middleware side-effects)
  • vitest.config.ts + 2 test files (28 tests)

Modified files:

  • src/middleware/session.ts — Added authMethod, authTokenId, authScopes to Express.Request; skips cookie parsing when token already authed
  • src/routes/auth.ts — Mounts tokens router at /auth/tokens
  • src/server.ts — Wires tokenAuthMiddleware before sessionMiddleware

Design decisions

  • Failure-only rate limiting on token auth (10 failures/min/IP) — valid requests are never counted
  • Case-insensitive, whitespace-tolerant Bearer parsing (/^Bearer\s+(.+)$/i)
  • Strict ownership: when oba_ header is present, middleware owns the response — no silent fallback to cookies
  • Scopes stored but not enforced — future-proofed via req.authScopes without needing another migration
  • Cache-Control: no-store on all token management endpoints (including error paths)
  • No new npm dependencies

Test plan

  • pnpm build passes
  • pnpm test — 28/28 tests pass (13 middleware, 15 route)
  • Run migration against Neon DB
  • Manual flow: GitHub OAuth login → create token → use token on /keys → list tokens → revoke → verify revoked token fails

🤖 Generated with Claude Code

hammadtq and others added 5 commits January 31, 2026 23:39
Bearer token auth (Authorization: Bearer oba_...) lets CLIs and agents
call authenticated endpoints without a browser session. Token management
endpoints (create/list/revoke) remain session-cookie-only to prevent
token-bootstrap attacks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…dation

- Rate-limit only auth failures, not all token-auth attempts (production breaker)
- Case-insensitive, whitespace-tolerant Bearer header parsing
- Add Cache-Control: no-store to token create and list responses
- Validate scope array entries are strings before checking against allowlist
- Add tests for lowercase "bearer" and extra whitespace

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…boundary

- Move hashToken into utils/crypto.ts so tokens.ts does not import
  rate-limiter side-effects from token-auth.ts
- Set Cache-Control: no-store at top of POST/GET handlers to cover
  error responses too
- Use <= instead of < for expiry check to reject tokens at exact
  expiration moment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- catch block in token-auth now uses fail() so error-spam brute-force
  gets 429 instead of unlimited 500s
- Remove unused beforeEach import in token-auth tests
- Add Cache-Control: no-store to DELETE handler for symmetry

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add beforeEach to reset ipCounter so watch-mode reruns don't
  accumulate IPs past 10.0.0.255
- Check Array.isArray(scopes) before applying nullish default so
  non-array inputs (string, number) are caught and the type
  annotation is honest

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to 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.

2 participants