[PR #8548] feat(auth): support function-based dynamic baseURL config #24954

Open
opened 2026-04-15 22:39:11 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8548
Author: @RaeesBhatti
Created: 3/11/2026
Status: 🔄 Open

Base: nextHead: dynamic-base-url-resolution


📝 Commits (4)

  • ac88371 feat(auth): support function-based dynamic baseURL config
  • b9a57f5 test(auth): add unit and behavioral tests for function baseURL
  • d06f2d7 docs: document function-based dynamic baseURL
  • a3671ed docs: remove unvalidated Host header examples from baseURL docs

📊 Changes

12 files changed (+831 additions, -32 deletions)

View changed files

📝 docs/content/docs/concepts/cookies.mdx (+22 -0)
📝 docs/content/docs/concepts/dynamic-base-url.mdx (+160 -6)
📝 docs/content/docs/reference/options.mdx (+21 -0)
📝 packages/better-auth/src/auth/base.ts (+14 -7)
📝 packages/better-auth/src/auth/full.test.ts (+370 -0)
📝 packages/better-auth/src/context/create-context.ts (+6 -2)
📝 packages/better-auth/src/cookies/index.ts (+2 -2)
📝 packages/better-auth/src/plugins/mcp/index.ts (+5 -10)
📝 packages/better-auth/src/test-utils/test-instance.ts (+2 -2)
📝 packages/better-auth/src/utils/url.test.ts (+159 -0)
📝 packages/better-auth/src/utils/url.ts (+57 -1)
📝 packages/core/src/types/init-options.ts (+13 -2)

📄 Description

Summary

Allow baseURL to accept (request: Request) => Awaitable<string> for multi-tenant and white-label apps where valid domains are stored in a database and not known at deploy time. This completes the work started in #8009 (allowedHosts), which only covers static domain lists.

  • Extends BaseURLConfig type to include function variant alongside string and DynamicBaseURLConfig
  • Reuses the per-request context isolation (Object.create) from the allowedHosts feature — no new architecture
  • Resolves the function to a string before downstream consumers access ctx.context.options.baseURL, so plugins, routes, and cookies need zero changes
  • Wraps user function errors in BetterAuthError with cause for debuggability
  • Simplifies MCP plugin's baseURL resolution from 3-way dispatch to 2-way

Test plan

  • 13 unit tests: type guards, sync/async resolution, error wrapping with cause preservation, invalid URL, null/undefined returns
  • 11 integration tests: context-level (baseURL resolution, async functions, concurrent isolation, trustedOrigins, crossSubDomainCookies) and behavioral (OAuth redirect_uri, handler error propagation, CSRF origin validation, Set-Cookie domain)
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm format:check passes

Fixes #4151


Summary by cubic

Add per-request function support for baseURL to enable multi-tenant and white-label setups where domains are resolved at runtime. Improves trusted-origin handling, cookies, OAuth/CSRF behavior, with updated docs and tests.

  • New Features
    • baseURL now accepts (request: Request) => Awaitable<string>, resolved per request and applied to ctx.context.baseURL and ctx.context.options.baseURL with per-request context isolation.
    • URL utils: added resolveFunctionBaseURL, isFunctionBaseURLConfig, and isPerRequestBaseURL; core, cookies, and mcp plugin use these for function resolution.
    • Trusted origins and cookies: resolved origin is auto-added for function configs; cross-subdomain cookies derive domain per request; OAuth redirect_uri and CSRF checks use the resolved host.
    • Validation and errors: empty/invalid URLs are rejected; function errors are wrapped in BetterAuthError with cause; clearer error messages; docs expanded with function patterns and security guidance (unsafe Host header examples removed); unit and integration tests added (sync/async, isolation, OAuth, CSRF, Set-Cookie).

Written for commit a3671edddb. 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/8548 **Author:** [@RaeesBhatti](https://github.com/RaeesBhatti) **Created:** 3/11/2026 **Status:** 🔄 Open **Base:** `next` ← **Head:** `dynamic-base-url-resolution` --- ### 📝 Commits (4) - [`ac88371`](https://github.com/better-auth/better-auth/commit/ac88371e23bc7ab688db44c92157f23f9cb555ce) feat(auth): support function-based dynamic baseURL config - [`b9a57f5`](https://github.com/better-auth/better-auth/commit/b9a57f5cbaea711881b817903e6e0c1062192039) test(auth): add unit and behavioral tests for function baseURL - [`d06f2d7`](https://github.com/better-auth/better-auth/commit/d06f2d7dfc5db6e9a644f45965aaf705134943e6) docs: document function-based dynamic baseURL - [`a3671ed`](https://github.com/better-auth/better-auth/commit/a3671edddb7c91fcfa0b7fe47df4dc250520e70f) docs: remove unvalidated Host header examples from baseURL docs ### 📊 Changes **12 files changed** (+831 additions, -32 deletions) <details> <summary>View changed files</summary> 📝 `docs/content/docs/concepts/cookies.mdx` (+22 -0) 📝 `docs/content/docs/concepts/dynamic-base-url.mdx` (+160 -6) 📝 `docs/content/docs/reference/options.mdx` (+21 -0) 📝 `packages/better-auth/src/auth/base.ts` (+14 -7) 📝 `packages/better-auth/src/auth/full.test.ts` (+370 -0) 📝 `packages/better-auth/src/context/create-context.ts` (+6 -2) 📝 `packages/better-auth/src/cookies/index.ts` (+2 -2) 📝 `packages/better-auth/src/plugins/mcp/index.ts` (+5 -10) 📝 `packages/better-auth/src/test-utils/test-instance.ts` (+2 -2) 📝 `packages/better-auth/src/utils/url.test.ts` (+159 -0) 📝 `packages/better-auth/src/utils/url.ts` (+57 -1) 📝 `packages/core/src/types/init-options.ts` (+13 -2) </details> ### 📄 Description ## Summary Allow `baseURL` to accept `(request: Request) => Awaitable<string>` for multi-tenant and white-label apps where valid domains are stored in a database and not known at deploy time. This completes the work started in #8009 (allowedHosts), which only covers static domain lists. - Extends `BaseURLConfig` type to include function variant alongside string and `DynamicBaseURLConfig` - Reuses the per-request context isolation (`Object.create`) from the allowedHosts feature — no new architecture - Resolves the function to a string before downstream consumers access `ctx.context.options.baseURL`, so plugins, routes, and cookies need zero changes - Wraps user function errors in `BetterAuthError` with `cause` for debuggability - Simplifies MCP plugin's baseURL resolution from 3-way dispatch to 2-way ## Test plan - [x] 13 unit tests: type guards, sync/async resolution, error wrapping with cause preservation, invalid URL, null/undefined returns - [x] 11 integration tests: context-level (baseURL resolution, async functions, concurrent isolation, trustedOrigins, crossSubDomainCookies) and behavioral (OAuth redirect_uri, handler error propagation, CSRF origin validation, Set-Cookie domain) - [x] `pnpm typecheck` passes - [x] `pnpm lint` passes - [x] `pnpm format:check` passes Fixes #4151 <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Add per-request function support for `baseURL` to enable multi-tenant and white-label setups where domains are resolved at runtime. Improves trusted-origin handling, cookies, OAuth/CSRF behavior, with updated docs and tests. - **New Features** - `baseURL` now accepts `(request: Request) => Awaitable<string>`, resolved per request and applied to `ctx.context.baseURL` and `ctx.context.options.baseURL` with per-request context isolation. - URL utils: added `resolveFunctionBaseURL`, `isFunctionBaseURLConfig`, and `isPerRequestBaseURL`; core, cookies, and `mcp` plugin use these for function resolution. - Trusted origins and cookies: resolved origin is auto-added for function configs; cross-subdomain cookies derive `domain` per request; OAuth `redirect_uri` and CSRF checks use the resolved host. - Validation and errors: empty/invalid URLs are rejected; function errors are wrapped in `BetterAuthError` with `cause`; clearer error messages; docs expanded with function patterns and security guidance (unsafe Host header examples removed); unit and integration tests added (sync/async, isolation, OAuth, CSRF, Set-Cookie). <sup>Written for commit a3671edddb7c91fcfa0b7fe47df4dc250520e70f. 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-15 22:39:11 -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#24954