[PR #8931] feat(session): support JWKS-backed JWT session cookie cache #16552

Open
opened 2026-04-13 10:34:20 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8931
Author: @GautamBytes
Created: 4/3/2026
Status: 🔄 Open

Base: nextHead: feat/jwks-session-support


📝 Commits (5)

  • a8ca0f5 feat(session): support JWKS-backed jwt cookie cache
  • fadad02 refactor(jwt): simplify cookie cache key source typing
  • 106ab38 Merge branch 'next' into feat/jwks-session-support
  • 94b23d5 chore(changeset): add JWKS session cookie release note
  • 6129a76 Merge branch 'next' into feat/jwks-session-support

📊 Changes

13 files changed (+821 additions, -34 deletions)

View changed files

.changeset/pr-8931.md (+5 -0)
📝 docs/content/docs/concepts/cookies.mdx (+10 -2)
📝 docs/content/docs/concepts/session-management.mdx (+28 -2)
📝 docs/content/docs/plugins/jwt.mdx (+6 -0)
📝 docs/content/docs/reference/options.mdx (+6 -1)
📝 packages/better-auth/src/api/routes/session-api.test.ts (+186 -0)
📝 packages/better-auth/src/api/routes/session.ts (+22 -9)
📝 packages/better-auth/src/context/create-context.test.ts (+84 -0)
📝 packages/better-auth/src/context/create-context.ts (+33 -0)
📝 packages/better-auth/src/cookies/cookies.test.ts (+204 -3)
📝 packages/better-auth/src/cookies/index.ts (+56 -17)
packages/better-auth/src/plugins/jwt/cookie-cache.ts (+167 -0)
📝 packages/core/src/types/init-options.ts (+14 -0)

📄 Description

Summary

This adds opt-in JWKS-backed asymmetric signing for cookie-cache JWT session data.

Closes #8923

Better Auth already supports asymmetric JWTs and JWKS via the jwt() plugin, but session.cookieCache.strategy = "jwt" was still using shared-secret HS256. That made session_data cookies impossible to verify with JWKS-backed tooling and easy to confuse with JWT plugin tokens.

This change keeps the primary session_token cookie unchanged and only extends the session_data cookie-cache JWT path.

What changed

  • Added session.cookieCache.jwt.keySource with:
    • "secret": existing HS256 behavior, still the default
    • "jwks": new asymmetric JWKS-backed signing mode
  • Added dedicated cookie-cache JWT helpers that:
    • sign with the JWT plugin’s latest asymmetric key
    • include kid
    • verify against local JWKS keys without network fetches
  • Updated session cookie-cache read/write flows to use JWKS mode when enabled
  • Extended getCookieCache() so callers can verify JWKS-backed cookie-cache JWTs by passing explicit JWKS input
  • Added guardrails:
    • JWKS mode requires the jwt() plugin
    • JWKS mode rejects custom remote jwt.sign
    • warning when cookie-cache maxAge exceeds JWKS grace period
  • Updated docs to clearly distinguish:
    • session_token
    • session_data
    • JWT plugin /token and set-auth-jwt

Notes

  • This does not change the primary session_token cookie.
  • JWKS mode is explicit and fully backward compatible.
  • Full package test/typecheck are not fully green in this repo due to unrelated pre-existing failures/noise outside this change.

Summary by cubic

Adds opt‑in JWKS‑backed asymmetric signing for the session_data cookie‑cache JWT so external services can verify it using the JWT plugin’s JWKS. The primary session_token cookie is unchanged and defaults remain secret‑backed for backward compatibility.

  • New Features

    • Added session.cookieCache.jwt.keySource: "secret" (HS256, default) or "jwks" (asymmetric via jwt()).
    • In JWKS mode, cookie‑cache JWTs set kid, sign with the plugin’s latest key, verify locally (no network), and honor the JWKS rotation grace period.
    • Updated server read/write flows and getCookieCache() to support JWKS mode; the helper requires jwt: { keySource: "jwks", jwks }.
    • Guardrails: requires jwt() and strategy: "jwt", rejects custom jwt({ jwt: { sign } }), warns if cookieCache.maxAge exceeds the JWKS grace period. Docs clarify session_token vs session_data; compact is the default strategy.
  • Migration

    • To enable JWKS mode: install jwt() and set session.cookieCache = { enabled: true, strategy: "jwt", jwt: { keySource: "jwks" } }.
    • For client verification with getCookieCache(), pass JWKS: { strategy: "jwt", jwt: { keySource: "jwks", jwks } }.

Written for commit 6129a76aad. Summary will update on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8931 **Author:** [@GautamBytes](https://github.com/GautamBytes) **Created:** 4/3/2026 **Status:** 🔄 Open **Base:** `next` ← **Head:** `feat/jwks-session-support` --- ### 📝 Commits (5) - [`a8ca0f5`](https://github.com/better-auth/better-auth/commit/a8ca0f5bc9ff795c60b2d582d6dfbc810014b266) feat(session): support JWKS-backed jwt cookie cache - [`fadad02`](https://github.com/better-auth/better-auth/commit/fadad02b8f4c387b78db9024eb7a609dc18ada73) refactor(jwt): simplify cookie cache key source typing - [`106ab38`](https://github.com/better-auth/better-auth/commit/106ab382274f0d4e8c686a1f7ee0186adc32f48f) Merge branch 'next' into feat/jwks-session-support - [`94b23d5`](https://github.com/better-auth/better-auth/commit/94b23d5ed42a33d4c33f35cd0b12038e2f4fd417) chore(changeset): add JWKS session cookie release note - [`6129a76`](https://github.com/better-auth/better-auth/commit/6129a76aad149a7efb7767ea1c3e94d4dbbb6724) Merge branch 'next' into feat/jwks-session-support ### 📊 Changes **13 files changed** (+821 additions, -34 deletions) <details> <summary>View changed files</summary> ➕ `.changeset/pr-8931.md` (+5 -0) 📝 `docs/content/docs/concepts/cookies.mdx` (+10 -2) 📝 `docs/content/docs/concepts/session-management.mdx` (+28 -2) 📝 `docs/content/docs/plugins/jwt.mdx` (+6 -0) 📝 `docs/content/docs/reference/options.mdx` (+6 -1) 📝 `packages/better-auth/src/api/routes/session-api.test.ts` (+186 -0) 📝 `packages/better-auth/src/api/routes/session.ts` (+22 -9) 📝 `packages/better-auth/src/context/create-context.test.ts` (+84 -0) 📝 `packages/better-auth/src/context/create-context.ts` (+33 -0) 📝 `packages/better-auth/src/cookies/cookies.test.ts` (+204 -3) 📝 `packages/better-auth/src/cookies/index.ts` (+56 -17) ➕ `packages/better-auth/src/plugins/jwt/cookie-cache.ts` (+167 -0) 📝 `packages/core/src/types/init-options.ts` (+14 -0) </details> ### 📄 Description ## Summary This adds opt-in JWKS-backed asymmetric signing for cookie-cache JWT session data. Closes #8923 Better Auth already supports asymmetric JWTs and JWKS via the `jwt()` plugin, but `session.cookieCache.strategy = "jwt"` was still using shared-secret HS256. That made `session_data` cookies impossible to verify with JWKS-backed tooling and easy to confuse with JWT plugin tokens. This change keeps the primary `session_token` cookie unchanged and only extends the `session_data` cookie-cache JWT path. ## What changed - Added `session.cookieCache.jwt.keySource` with: - `"secret"`: existing HS256 behavior, still the default - `"jwks"`: new asymmetric JWKS-backed signing mode - Added dedicated cookie-cache JWT helpers that: - sign with the JWT plugin’s latest asymmetric key - include `kid` - verify against local JWKS keys without network fetches - Updated session cookie-cache read/write flows to use JWKS mode when enabled - Extended `getCookieCache()` so callers can verify JWKS-backed cookie-cache JWTs by passing explicit JWKS input - Added guardrails: - JWKS mode requires the `jwt()` plugin - JWKS mode rejects custom remote `jwt.sign` - warning when cookie-cache `maxAge` exceeds JWKS grace period - Updated docs to clearly distinguish: - `session_token` - `session_data` - JWT plugin `/token` and `set-auth-jwt` ## Notes - This does **not** change the primary `session_token` cookie. - JWKS mode is explicit and fully backward compatible. - Full package test/typecheck are not fully green in this repo due to unrelated pre-existing failures/noise outside this change. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds opt‑in JWKS‑backed asymmetric signing for the `session_data` cookie‑cache JWT so external services can verify it using the JWT plugin’s JWKS. The primary `session_token` cookie is unchanged and defaults remain secret‑backed for backward compatibility. - **New Features** - Added `session.cookieCache.jwt.keySource`: `"secret"` (HS256, default) or `"jwks"` (asymmetric via `jwt()`). - In JWKS mode, cookie‑cache JWTs set `kid`, sign with the plugin’s latest key, verify locally (no network), and honor the JWKS rotation grace period. - Updated server read/write flows and `getCookieCache()` to support JWKS mode; the helper requires `jwt: { keySource: "jwks", jwks }`. - Guardrails: requires `jwt()` and `strategy: "jwt"`, rejects custom `jwt({ jwt: { sign } })`, warns if `cookieCache.maxAge` exceeds the JWKS grace period. Docs clarify `session_token` vs `session_data`; `compact` is the default strategy. - **Migration** - To enable JWKS mode: install `jwt()` and set `session.cookieCache = { enabled: true, strategy: "jwt", jwt: { keySource: "jwks" } }`. - For client verification with `getCookieCache()`, pass JWKS: `{ strategy: "jwt", jwt: { keySource: "jwks", jwks } }`. <sup>Written for commit 6129a76aad149a7efb7767ea1c3e94d4dbbb6724. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-13 10:34:20 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#16552