Troubleshooting: Invalid Origin Error After Upgrading Better Auth
After upgrading Better Auth, we encountered an Invalid origin ... error in our production environment:
2025-12-03T01:03:01.038Z ERROR [Better Auth]: Invalid origin: https://www.example.com
2025-12-03T01:03:01.038Z INFO [Better Auth]: If it's a valid URL, please add https://www.example.com to trustedOrigins in your auth config
Current list of trustedOrigins: https://0.0.0.0:3000
Before the upgrade, the service was working well.
Analysis
In its changelog, I found a change introduced in v1.4.3:
🚀 Features
- Add support for trusted proxy headers in base URL inference – @Bekacru
I digged deeply and confirmed that the issue came from a recent change introduced in PR#6285.
In earlier versions, better-auth automatically parsed X-Forwarded-* headers to determine the request’s origin, allowing it to handle requests behind reverse proxies seamlessly. However, to enhance security and mitigate the risk of header spoofing, the latest version no longer trusts these headers by default. Instead, it requires users to explicitly configure trusted origins.
Solutions
This issue can be resolved by one of the following methods:
1. baseURL or BETTER_AUTH_URL Environment Variable
The baseURL option and the BETTER_AUTH_URL environment variable are used to specify the primary origin of your application. Setting this will resolve the “Invalid origin” error for your main domain.
import { betterAuth } from "better-auth";
export const auth = betterAuth({
baseURL: "https://example.com",
});
2. Configure trustedOrigins
The trustedOrigins option accepts an array of authorized URLs. This is ideal if your application needs to support multiple domains. It supports both static and dynamic configurations:
Static Configuration:
import { betterAuth } from "better-auth";
export const auth = betterAuth({
trustedOrigins: ["http://localhost:3000", "https://example.com"],
});
Dynamic Configuration:
export const auth = betterAuth({
trustedOrigins: async (request: Request) => {
// Return an array of trusted origins based on the incoming request
return ["https://dynamic-origin.com"];
},
});
3. Enable advanced.trustedProxyHeaders
As of this writing, this parameter is not yet listed in the official documentation. However, as seen in PR#6285, enabling this flag instructs better-auth to trust X-Forwarded-* headers again, restoring the legacy behavior.
Warning: Use this with caution. Ensure your application is strictly served behind a trusted reverse proxy and is not directly exposed to the public internet.
import { betterAuth } from "better-auth";
export const auth = betterAuth({
advanced: {
trustedProxyHeaders: true,
},
});