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

Open
opened 2026-03-13 13:58:27 -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: canaryHead: dynamic-base-url-resolution


📝 Commits (4)

  • b66c193 feat(auth): support function-based dynamic baseURL config
  • 53038cd test(auth): add unit and behavioral tests for function baseURL
  • d6deeb7 docs: document function-based dynamic baseURL
  • ed5c7f4 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 support for function-based baseURL that resolves per request, enabling multi-tenant and white-label setups without pre-known domains. Docs updated with safer examples that avoid unvalidated Host header usage.

  • New Features
    • baseURL now accepts (request: Request) => Awaitable<string> in addition to string and DynamicBaseURLConfig, resolved with per-request context isolation and applied to ctx.context.baseURL and ctx.context.options.baseURL.
    • Errors are wrapped in BetterAuthError with cause; validates non-empty and valid URLs.
    • Resolved origin is added to trustedOrigins; cross-subdomain cookies derive the correct domain; mcp auth baseURL resolution simplified.
    • Docs updated: Dynamic Base URL, Options, and Cookies pages now cover function usage, patterns, and security notes, with hardened examples that avoid unvalidated Host header patterns.
    • Added unit and integration tests for sync/async resolution, error propagation, OAuth redirect_uri, CSRF origin checks, Set-Cookie domain, and concurrent isolation.

Written for commit ed5c7f4fc06241422d75971cd1b8d8b04271ecd1. 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:** `canary` ← **Head:** `dynamic-base-url-resolution` --- ### 📝 Commits (4) - [`b66c193`](https://github.com/better-auth/better-auth/commit/b66c1931cc8176932d1a82b78b4df3aca4a95dec) feat(auth): support function-based dynamic baseURL config - [`53038cd`](https://github.com/better-auth/better-auth/commit/53038cdd8dfd53267984510d99537368d2c8a175) test(auth): add unit and behavioral tests for function baseURL - [`d6deeb7`](https://github.com/better-auth/better-auth/commit/d6deeb7f63d4f848f932fae4cf569f0f283dd098) docs: document function-based dynamic baseURL - [`ed5c7f4`](https://github.com/better-auth/better-auth/commit/ed5c7f4fc06241422d75971cd1b8d8b04271ecd1) 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 support for function-based baseURL that resolves per request, enabling multi-tenant and white-label setups without pre-known domains. Docs updated with safer examples that avoid unvalidated Host header usage. - New Features - `baseURL` now accepts `(request: Request) => Awaitable<string>` in addition to string and `DynamicBaseURLConfig`, resolved with per-request context isolation and applied to `ctx.context.baseURL` and `ctx.context.options.baseURL`. - Errors are wrapped in `BetterAuthError` with `cause`; validates non-empty and valid URLs. - Resolved origin is added to `trustedOrigins`; cross-subdomain cookies derive the correct domain; `mcp` auth baseURL resolution simplified. - Docs updated: Dynamic Base URL, Options, and Cookies pages now cover function usage, patterns, and security notes, with hardened examples that avoid unvalidated Host header patterns. - Added unit and integration tests for sync/async resolution, error propagation, OAuth `redirect_uri`, CSRF origin checks, `Set-Cookie` domain, and concurrent isolation. <sup>Written for commit ed5c7f4fc06241422d75971cd1b8d8b04271ecd1. 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-03-13 13:58:27 -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#8054