fix: secure authentication request identity
Replace Better Auth's default trust of a caller-controlled X-Forwarded-For with a platform-owned client-address resolution boundary: direct mode (the safe default) trusts only the real socket peer, and an explicit trusted-proxy mode requires a header name, a concrete trusted-proxy list, and only honors a forwarded chain from an actual trusted peer. This closes a rate-limit bypass where rotating a spoofed header let a caller choose a fresh bucket on every request. Public sign-up is also disabled by default and requires an explicit typed opt-in, using Better Auth's own disableSignUp gate so no email-existence leak or second signup path is introduced. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
5e09330001
commit
cafd513019
+12
-1
@@ -119,7 +119,18 @@ export function createApiApp(options: CreateApiAppOptions): Hono {
|
||||
|
||||
app.on(["POST", "GET"], "/api/auth/*", async (c) => {
|
||||
try {
|
||||
return await runtime.handleAuthRequest(c.req.raw);
|
||||
const response = await runtime.handleAuthRequest(c.req.raw);
|
||||
// Every Better Auth response — including a session cookie — must never be cached by an
|
||||
// intermediary; constructing a fresh Response (rather than relying on `c.header()`, which
|
||||
// only affects `c.res`) guarantees this regardless of how the handler produced its result,
|
||||
// and never reads or buffers the body.
|
||||
const headers = new Headers(response.headers);
|
||||
headers.set("Cache-Control", "no-store");
|
||||
return new Response(response.body, {
|
||||
headers,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
});
|
||||
} catch (error) {
|
||||
return sanitizedErrorResponse(c, error, 500);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user