Skip to content

feat(agent-bff): mode 1 oauth session core (issue tokens)#1715

Open
Tonours wants to merge 20 commits into
feature/prd-647-scaffold-the-agent-bff-packagefrom
feature/prd-664-agent-nodejs-mode-1-oauth-session-core-issue-tokens
Open

feat(agent-bff): mode 1 oauth session core (issue tokens)#1715
Tonours wants to merge 20 commits into
feature/prd-647-scaffold-the-agent-bff-packagefrom
feature/prd-664-agent-nodejs-mode-1-oauth-session-core-issue-tokens

Conversation

@Tonours

@Tonours Tonours commented Jun 26, 2026

Copy link
Copy Markdown
Member

fixes PRD-664

Stacked on #1710 (agent-bff scaffold). Base this PR on feature/prd-647-...; it retargets to main once #1710 merges.

What this adds

Mode 1 OAuth session core for the BFF (packages/agent-bff): the browser completes the authorization-code flow and the BFF issues its own session — a short-lived BFF access JWT + an opaque refresh token. The upstream Forest server tokens stay server-side; the browser never sees one.

Builds on the PRD-649 spike (S2S code-exchange), promoted to production with hardening.

Scope

Two endpoints + the supporting layer:

  • GET /oauth/authorize — validates the request (client registered, redirect_uri match, response_type=code, mandatory code_challenge_method=S256) and forwards client-owned PKCE + state to the Forest server.
  • POST /oauth/token (grant_type=authorization_code) — exchanges the code, resolves identity, creates a session, returns { access_token, token_type, expires_in, refresh_token }.
  • BFF access JWT: type: bff_access, sid, whitelisted identity claims + tags, expiresIn = min(15m, remaining server-token lifetime), signed HS256.
  • Opaque 256-bit refresh token: issued here, stored hashed (SHA-256). The refresh grant (rotation/reuse-detection) is T5/PRD-665 — out of scope.
  • Server-token store: in-memory (prod = Redis), the upstream refresh token encrypted at rest (AES-256-GCM, BFF_TOKEN_ENCRYPTION_KEY).
  • Authorization-code single-use replay guard (atomic claim before exchange) with TTL + a hard cap (memory-DoS bound).
  • Lazy server-token refresh helper (ensureFreshServerAccess, single-flight per session) — wired into the request path by Slice 3.

What does NOT change

No refresh-token grant (T5), no CORS/timezone/edge wiring (T6), no real agent call (Slice 3), no cross-origin proof (G1). No other package touched.

Security

  • Upstream server tokens never appear in any response body, JWT payload, or log line (asserted with sentinel values).
  • Upstream refresh encrypted at rest; opaque refresh stored hashed; JWT pinned to HS256.
  • client_id percent-encoded into the S2S URL (no path injection); registry outage surfaces as a server error, not a misleading invalid_client.
  • Authorization-code claim is single-use + capped to bound a memory-DoS vector on the unauthenticated token endpoint.

How to test

yarn workspace @forestadmin/agent-bff test   # 133 tests
yarn workspace @forestadmin/agent-bff lint
yarn workspace @forestadmin/agent-bff build

Boot with full OAuth config (incl. BFF_TOKEN_ENCRYPTION_KEY, base64 32 bytes) to enable the routes; drop any required var → routes disabled, server still boots (/health degraded).

Definition of Done

General

  • Write an explicit title for the Pull Request, following Conventional Commits specification
  • Test manually the implemented changes
  • Validate the code quality (indentation, syntax, style, simplicity, readability)

Security

  • Consider the security impact of the changes made

@linear-code

linear-code Bot commented Jun 26, 2026

Copy link
Copy Markdown

PRD-664

@qltysh

qltysh Bot commented Jun 26, 2026

Copy link
Copy Markdown

4 new issues

Tool Category Rule Count
qlty Structure Function with high complexity (count = 11): constructor 2
qlty Structure Complex binary expression 1
qlty Structure Function with many returns (count = 4): createInMemorySessionStore 1

@qltysh

qltysh Bot commented Jun 26, 2026

Copy link
Copy Markdown

Qlty


Coverage Impact

⬆️ Merging this pull request will increase total coverage on feature/prd-647-scaffold-the-agent-bff-package by 0.12%.

Modified Files with Diff Coverage (13)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/agent-bff/src/cli-core.ts95.8%62
Coverage rating: A Coverage rating: A
packages/agent-bff/src/config/env-config.ts100.0%
Coverage rating: A Coverage rating: A
packages/agent-bff/src/http/bff-http-server.ts100.0%
Coverage rating: A Coverage rating: A
packages/agent-bff/src/index.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/forest-server-client.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/oauth-routes.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/pkce.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/bff-token.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/token-cipher.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/session-lifecycle.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/session-store.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/oauth-exchange-error.ts100.0%
New Coverage rating: A
packages/agent-bff/src/oauth/oauth-error.ts100.0%
Total99.7%
🤖 Increase coverage with AI coding...
In the `feature/prd-664-agent-nodejs-mode-1-oauth-session-core-issue-tokens` branch, add test coverage for this new code:

- `packages/agent-bff/src/cli-core.ts` -- Line 62

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

Comment thread packages/agent-bff/src/oauth/forest-server-client.ts
Comment thread packages/agent-bff/src/oauth/session-store.ts
Comment thread packages/agent-bff/src/oauth/session-store.ts
Comment thread packages/agent-bff/src/oauth/oauth-routes.ts
Comment thread packages/agent-bff/src/cli-core.ts Outdated
Comment thread packages/agent-bff/src/oauth/session-lifecycle.ts Outdated
Comment thread packages/agent-bff/src/oauth/oauth-routes.ts
@Tonours Tonours force-pushed the feature/prd-664-agent-nodejs-mode-1-oauth-session-core-issue-tokens branch from bb33f7e to 8724553 Compare June 26, 2026 13:15
Comment thread packages/agent-bff/src/cli-core.ts
Comment thread packages/agent-bff/src/cli-core.ts
Comment thread packages/agent-bff/src/oauth/forest-server-client.ts Outdated
Comment thread packages/agent-bff/src/oauth/oauth-routes.ts
Comment thread packages/agent-bff/src/oauth/session-store.ts Outdated
Comment thread packages/agent-bff/src/oauth/session-lifecycle.ts Outdated
@Tonours Tonours force-pushed the feature/prd-664-agent-nodejs-mode-1-oauth-session-core-issue-tokens branch from 6e349be to a35a769 Compare June 26, 2026 14:15
Comment thread packages/agent-bff/src/oauth/bff-token.ts Outdated
Comment thread packages/agent-bff/src/oauth/forest-server-client.ts
Comment thread packages/agent-bff/src/oauth/oauth-routes.ts
Comment thread packages/agent-bff/src/oauth/session-store.ts Outdated
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.

1 participant