From d313d0093e97dea57879be9dfd43143275380010 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Mon, 4 Aug 2025 10:27:55 -0700 Subject: [PATCH] fix: await `ctx` in middleware (#3783) * fix: await ctx in middleware * fix: lint * Create tidy-impalas-fail.md --- .changeset/tidy-impalas-fail.md | 5 ++ packages/better-auth/src/api/index.test.ts | 54 ++++++++++++++++++++++ packages/better-auth/src/api/index.ts | 3 +- 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 .changeset/tidy-impalas-fail.md create mode 100644 packages/better-auth/src/api/index.test.ts diff --git a/.changeset/tidy-impalas-fail.md b/.changeset/tidy-impalas-fail.md new file mode 100644 index 0000000000..9ba9e12001 --- /dev/null +++ b/.changeset/tidy-impalas-fail.md @@ -0,0 +1,5 @@ +--- +"better-auth": patch +--- + +fix: await `ctx` in middleware diff --git a/packages/better-auth/src/api/index.test.ts b/packages/better-auth/src/api/index.test.ts new file mode 100644 index 0000000000..5391c1ae0c --- /dev/null +++ b/packages/better-auth/src/api/index.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it, vi } from "vitest"; +import { getEndpoints } from "./index"; +import type { AuthContext } from "../init"; +import type { BetterAuthOptions, BetterAuthPlugin } from "../types"; +import { createAuthMiddleware } from "./call"; + +describe("getEndpoints", () => { + it("should await promise-based context before passing to middleware", async () => { + const mockContext: AuthContext = { + baseURL: "http://localhost:3000", + options: {}, + } as any; + + const middlewareFn = vi.fn().mockResolvedValue({}); + + const testPlugin: BetterAuthPlugin = { + id: "test-plugin", + middlewares: [ + { + path: "/test", + middleware: createAuthMiddleware(async (ctx) => { + middlewareFn(ctx); + return {}; + }), + }, + ], + }; + + const options: BetterAuthOptions = { + plugins: [testPlugin], + }; + + const promiseContext = new Promise((resolve) => { + setTimeout(() => resolve(mockContext), 10); + }); + + const { middlewares } = getEndpoints(promiseContext, options); + + const testCtx = { + request: new Request("http://localhost:3000/test"), + context: { customProp: "value" }, + }; + + await middlewares[0].middleware(testCtx); + + expect(middlewareFn).toHaveBeenCalled(); + const call = middlewareFn.mock.calls[0][0]; + expect(call.context).toMatchObject({ + baseURL: "http://localhost:3000", + options: {}, + customProp: "value", + }); + }); +}); diff --git a/packages/better-auth/src/api/index.ts b/packages/better-auth/src/api/index.ts index 075b518ee0..7da3884165 100644 --- a/packages/better-auth/src/api/index.ts +++ b/packages/better-auth/src/api/index.ts @@ -72,10 +72,11 @@ export function getEndpoints< ?.map((plugin) => plugin.middlewares?.map((m) => { const middleware = (async (context: any) => { + const authContext = await ctx; return m.middleware({ ...context, context: { - ...ctx, + ...authContext, ...context.context, }, });