@convex-dev/better-auth 0.10.12 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-options.d.ts.map +1 -1
- package/dist/auth-options.js +0 -2
- package/dist/auth-options.js.map +1 -1
- package/dist/client/adapter-utils.d.ts +10 -10
- package/dist/client/adapter-utils.d.ts.map +1 -1
- package/dist/client/adapter-utils.js +41 -32
- package/dist/client/adapter-utils.js.map +1 -1
- package/dist/client/adapter.d.ts +1 -1
- package/dist/client/adapter.d.ts.map +1 -1
- package/dist/client/adapter.js +113 -7
- package/dist/client/adapter.js.map +1 -1
- package/dist/client/create-api.d.ts +8 -7
- package/dist/client/create-api.d.ts.map +1 -1
- package/dist/client/create-api.js +1 -0
- package/dist/client/create-api.js.map +1 -1
- package/dist/client/create-client.d.ts +1 -1
- package/dist/client/create-client.d.ts.map +1 -1
- package/dist/client/create-client.js +8 -7
- package/dist/client/create-client.js.map +1 -1
- package/dist/client/create-schema.d.ts +0 -1
- package/dist/client/create-schema.d.ts.map +1 -1
- package/dist/client/create-schema.js +0 -1
- package/dist/client/create-schema.js.map +1 -1
- package/dist/component/_generated/api.d.ts +12 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +7407 -92
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/adapter.d.ts +8 -7
- package/dist/component/adapter.d.ts.map +1 -1
- package/dist/component/adapterTest.d.ts +1 -7
- package/dist/component/adapterTest.d.ts.map +1 -1
- package/dist/component/adapterTest.js +193 -390
- package/dist/component/adapterTest.js.map +1 -1
- package/dist/component/schema.d.ts +35 -74
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +16 -21
- package/dist/component/schema.js.map +1 -1
- package/dist/component/testProfiles/adapterAdditionalFields.d.ts +131 -0
- package/dist/component/testProfiles/adapterAdditionalFields.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterAdditionalFields.js +5 -0
- package/dist/component/testProfiles/adapterAdditionalFields.js.map +1 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.d.ts +131 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.js +5 -0
- package/dist/component/testProfiles/adapterOrganizationJoins.js.map +1 -0
- package/dist/component/testProfiles/adapterPluginTable.d.ts +131 -0
- package/dist/component/testProfiles/adapterPluginTable.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterPluginTable.js +5 -0
- package/dist/component/testProfiles/adapterPluginTable.js.map +1 -0
- package/dist/component/testProfiles/adapterRenameField.d.ts +131 -0
- package/dist/component/testProfiles/adapterRenameField.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterRenameField.js +5 -0
- package/dist/component/testProfiles/adapterRenameField.js.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.d.ts +131 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.js +5 -0
- package/dist/component/testProfiles/adapterRenameUserCustom.js.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserTable.d.ts +131 -0
- package/dist/component/testProfiles/adapterRenameUserTable.d.ts.map +1 -0
- package/dist/component/testProfiles/adapterRenameUserTable.js +5 -0
- package/dist/component/testProfiles/adapterRenameUserTable.js.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.d.ts +3 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.d.ts.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.js +38 -0
- package/dist/component/testProfiles/auth-options.profile-additional-fields.js.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.d.ts +3 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.d.ts.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.js +92 -0
- package/dist/component/testProfiles/auth-options.profile-plugin-table.js.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.d.ts +6 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.d.ts.map +1 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.js +49 -0
- package/dist/component/testProfiles/auth-options.profile-rename-joins.js.map +1 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.d.ts +227 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.d.ts.map +1 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.js +37 -0
- package/dist/component/testProfiles/schema.profile-additional-fields.js.map +1 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.d.ts +450 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.d.ts.map +1 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.js +116 -0
- package/dist/component/testProfiles/schema.profile-plugin-table.js.map +1 -0
- package/dist/nextjs/index.d.ts.map +1 -1
- package/dist/nextjs/index.js +1 -0
- package/dist/nextjs/index.js.map +1 -1
- package/dist/plugins/convex/index.d.ts +131 -12
- package/dist/plugins/convex/index.d.ts.map +1 -1
- package/dist/plugins/convex/index.js +12 -5
- package/dist/plugins/convex/index.js.map +1 -1
- package/dist/plugins/cross-domain/client.d.ts +1 -1
- package/dist/plugins/cross-domain/index.d.ts +126 -1
- package/dist/plugins/cross-domain/index.d.ts.map +1 -1
- package/dist/plugins/cross-domain/index.js +11 -16
- package/dist/plugins/cross-domain/index.js.map +1 -1
- package/dist/react-start/index.d.ts.map +1 -1
- package/dist/react-start/index.js +1 -0
- package/dist/react-start/index.js.map +1 -1
- package/dist/test/adapter-factory/auth-flow.d.ts +42 -0
- package/dist/test/adapter-factory/auth-flow.d.ts.map +1 -0
- package/dist/test/adapter-factory/auth-flow.js +145 -0
- package/dist/test/adapter-factory/auth-flow.js.map +1 -0
- package/dist/test/adapter-factory/basic.d.ts +190 -0
- package/dist/test/adapter-factory/basic.d.ts.map +1 -0
- package/dist/test/adapter-factory/basic.js +2713 -0
- package/dist/test/adapter-factory/basic.js.map +1 -0
- package/dist/test/adapter-factory/convex-custom.d.ts +18 -0
- package/dist/test/adapter-factory/convex-custom.d.ts.map +1 -0
- package/dist/test/adapter-factory/convex-custom.js +610 -0
- package/dist/test/adapter-factory/convex-custom.js.map +1 -0
- package/dist/test/adapter-factory/index.d.ts +11 -0
- package/dist/test/adapter-factory/index.d.ts.map +1 -0
- package/dist/test/adapter-factory/index.js +11 -0
- package/dist/test/adapter-factory/index.js.map +1 -0
- package/dist/test/adapter-factory/joins.d.ts +18 -0
- package/dist/test/adapter-factory/joins.d.ts.map +1 -0
- package/dist/test/adapter-factory/joins.js +22 -0
- package/dist/test/adapter-factory/joins.js.map +1 -0
- package/dist/test/adapter-factory/number-id.d.ts +18 -0
- package/dist/test/adapter-factory/number-id.d.ts.map +1 -0
- package/dist/test/adapter-factory/number-id.js +36 -0
- package/dist/test/adapter-factory/number-id.js.map +1 -0
- package/dist/test/adapter-factory/profile-additional-fields.d.ts +71 -0
- package/dist/test/adapter-factory/profile-additional-fields.d.ts.map +1 -0
- package/dist/test/adapter-factory/profile-additional-fields.js +44 -0
- package/dist/test/adapter-factory/profile-additional-fields.js.map +1 -0
- package/dist/test/adapter-factory/profile-plugin-table.d.ts +19 -0
- package/dist/test/adapter-factory/profile-plugin-table.d.ts.map +1 -0
- package/dist/test/adapter-factory/profile-plugin-table.js +25 -0
- package/dist/test/adapter-factory/profile-plugin-table.js.map +1 -0
- package/dist/test/adapter-factory/profile-rename-joins.d.ts +73 -0
- package/dist/test/adapter-factory/profile-rename-joins.d.ts.map +1 -0
- package/dist/test/adapter-factory/profile-rename-joins.js +34 -0
- package/dist/test/adapter-factory/profile-rename-joins.js.map +1 -0
- package/dist/test/adapter-factory/transactions.d.ts +21 -0
- package/dist/test/adapter-factory/transactions.d.ts.map +1 -0
- package/dist/test/adapter-factory/transactions.js +28 -0
- package/dist/test/adapter-factory/transactions.js.map +1 -0
- package/dist/test/adapter-factory/uuid.d.ts +18 -0
- package/dist/test/adapter-factory/uuid.d.ts.map +1 -0
- package/dist/test/adapter-factory/uuid.js +58 -0
- package/dist/test/adapter-factory/uuid.js.map +1 -0
- package/dist/utils/index.d.ts +18 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js.map +1 -1
- package/package.json +9 -6
- package/src/auth-options.ts +0 -2
- package/src/client/adapter-utils.ts +80 -73
- package/src/client/adapter.test.ts +2 -74
- package/src/client/adapter.ts +142 -7
- package/src/client/create-api.ts +1 -0
- package/src/client/create-client.ts +14 -6
- package/src/client/create-schema.ts +0 -1
- package/src/component/_generated/api.ts +12 -0
- package/src/component/_generated/component.ts +19454 -215
- package/src/component/adapterTest.ts +250 -466
- package/src/component/schema.ts +21 -26
- package/src/component/testProfiles/adapterAdditionalFields.ts +13 -0
- package/src/component/testProfiles/adapterOrganizationJoins.ts +13 -0
- package/src/component/testProfiles/adapterPluginTable.ts +13 -0
- package/src/component/testProfiles/adapterRenameField.ts +13 -0
- package/src/component/testProfiles/adapterRenameUserCustom.ts +13 -0
- package/src/component/testProfiles/adapterRenameUserTable.ts +13 -0
- package/src/component/testProfiles/auth-options.profile-additional-fields.ts +39 -0
- package/src/component/testProfiles/auth-options.profile-plugin-table.ts +93 -0
- package/src/component/testProfiles/auth-options.profile-rename-joins.ts +54 -0
- package/src/component/testProfiles/schema.profile-additional-fields.ts +39 -0
- package/src/component/testProfiles/schema.profile-plugin-table.ts +130 -0
- package/src/nextjs/index.ts +1 -0
- package/src/plugins/convex/index.test.ts +55 -0
- package/src/plugins/convex/index.ts +26 -11
- package/src/plugins/cross-domain/index.test.ts +67 -0
- package/src/plugins/cross-domain/index.ts +11 -22
- package/src/react-start/index.ts +1 -0
- package/src/test/adapter-factory/auth-flow.ts +170 -0
- package/src/test/adapter-factory/basic.ts +3190 -0
- package/src/test/adapter-factory/convex-custom.ts +706 -0
- package/src/test/adapter-factory/index.ts +10 -0
- package/src/test/adapter-factory/joins.ts +28 -0
- package/src/test/adapter-factory/number-id.ts +45 -0
- package/src/test/adapter-factory/profile-additional-fields.ts +84 -0
- package/src/test/adapter-factory/profile-plugin-table.ts +37 -0
- package/src/test/adapter-factory/profile-rename-joins.ts +67 -0
- package/src/test/adapter-factory/transactions.ts +38 -0
- package/src/test/adapter-factory/uuid.ts +67 -0
- package/src/utils/index.ts +25 -3
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
BetterAuthPlugin,
|
|
3
|
-
Session,
|
|
4
|
-
User,
|
|
5
|
-
} from "better-auth";
|
|
1
|
+
import type { BetterAuthPlugin, Session, User } from "better-auth";
|
|
6
2
|
import type { BetterAuthOptions } from "better-auth/minimal";
|
|
7
|
-
import { createAuthMiddleware, sessionMiddleware } from "better-auth/api";
|
|
8
3
|
import {
|
|
9
4
|
createAuthEndpoint,
|
|
5
|
+
createAuthMiddleware,
|
|
6
|
+
sessionMiddleware,
|
|
7
|
+
} from "better-auth/api";
|
|
8
|
+
import {
|
|
10
9
|
jwt as jwtPlugin,
|
|
11
10
|
bearer as bearerPlugin,
|
|
12
11
|
oidcProvider as oidcProviderPlugin,
|
|
@@ -17,6 +16,21 @@ import type { AuthConfig, AuthProvider } from "convex/server";
|
|
|
17
16
|
|
|
18
17
|
export const JWT_COOKIE_NAME = "convex_jwt";
|
|
19
18
|
|
|
19
|
+
type BetterAuthAfterHooks = NonNullable<
|
|
20
|
+
NonNullable<BetterAuthPlugin["hooks"]>["after"]
|
|
21
|
+
>;
|
|
22
|
+
type BetterAuthAfterHook = BetterAuthAfterHooks[number];
|
|
23
|
+
type BetterAuthHookContext = Parameters<BetterAuthAfterHook["matcher"]>[0];
|
|
24
|
+
|
|
25
|
+
const normalizeAfterHooks = <THook extends BetterAuthAfterHook>(
|
|
26
|
+
hooks: THook[]
|
|
27
|
+
): BetterAuthAfterHooks => {
|
|
28
|
+
return hooks.map((hook) => ({
|
|
29
|
+
...hook,
|
|
30
|
+
matcher: (ctx: BetterAuthHookContext) => Boolean(hook.matcher(ctx)),
|
|
31
|
+
}));
|
|
32
|
+
};
|
|
33
|
+
|
|
20
34
|
const getJwksAlg = (authProvider: AuthProvider) => {
|
|
21
35
|
const isCustomJwt =
|
|
22
36
|
"type" in authProvider && authProvider.type === "customJwt";
|
|
@@ -280,7 +294,7 @@ export const convex = (opts: {
|
|
|
280
294
|
const knownSafePaths = ["/api-key/list", "/api-key/get"];
|
|
281
295
|
const noopWrite = (method: string) => {
|
|
282
296
|
return async (..._args: any[]) => {
|
|
283
|
-
if (!knownSafePaths.includes(ctx.path)) {
|
|
297
|
+
if (ctx.path && !knownSafePaths.includes(ctx.path)) {
|
|
284
298
|
// eslint-disable-next-line no-console
|
|
285
299
|
console.warn(
|
|
286
300
|
`[convex-better-auth] Write operation "${method}" skipped in query context for ${ctx.path}`
|
|
@@ -299,7 +313,7 @@ export const convex = (opts: {
|
|
|
299
313
|
},
|
|
300
314
|
],
|
|
301
315
|
after: [
|
|
302
|
-
...oidcProvider.hooks.after,
|
|
316
|
+
...normalizeAfterHooks(oidcProvider.hooks.after),
|
|
303
317
|
{
|
|
304
318
|
matcher: (ctx) => {
|
|
305
319
|
return Boolean(
|
|
@@ -311,6 +325,7 @@ export const convex = (opts: {
|
|
|
311
325
|
ctx.path?.startsWith("/email-otp/verify-email") ||
|
|
312
326
|
ctx.path?.startsWith("/phone-number/verify") ||
|
|
313
327
|
ctx.path?.startsWith("/siwe/verify") ||
|
|
328
|
+
ctx.path?.startsWith("/update-session") ||
|
|
314
329
|
(ctx.path?.startsWith("/get-session") && ctx.context.session)
|
|
315
330
|
);
|
|
316
331
|
},
|
|
@@ -341,10 +356,10 @@ export const convex = (opts: {
|
|
|
341
356
|
},
|
|
342
357
|
{
|
|
343
358
|
matcher: (ctx) => {
|
|
344
|
-
return (
|
|
359
|
+
return Boolean(
|
|
345
360
|
ctx.path?.startsWith("/sign-out") ||
|
|
346
|
-
|
|
347
|
-
|
|
361
|
+
ctx.path?.startsWith("/delete-user") ||
|
|
362
|
+
(ctx.path?.startsWith("/get-session") && !ctx.context.session)
|
|
348
363
|
);
|
|
349
364
|
},
|
|
350
365
|
handler: createAuthMiddleware(async (ctx) => {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { crossDomain } from "./index.js";
|
|
3
|
+
|
|
4
|
+
const getPostRewriteMatcher = () => {
|
|
5
|
+
const plugin = crossDomain({ siteUrl: "https://example.com" });
|
|
6
|
+
const matcher = plugin.hooks?.before?.[2]?.matcher;
|
|
7
|
+
if (!matcher) {
|
|
8
|
+
throw new Error("expected cross-domain POST rewrite matcher");
|
|
9
|
+
}
|
|
10
|
+
return matcher;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
describe("crossDomain POST rewrite matcher", () => {
|
|
14
|
+
it("matches POST requests regardless of route", () => {
|
|
15
|
+
const matcher = getPostRewriteMatcher();
|
|
16
|
+
type MatcherContext = Parameters<typeof matcher>[0];
|
|
17
|
+
|
|
18
|
+
const knownPathCtx = {
|
|
19
|
+
method: "POST",
|
|
20
|
+
path: "/sign-in/email",
|
|
21
|
+
headers: new Headers(),
|
|
22
|
+
} satisfies Partial<MatcherContext>;
|
|
23
|
+
const unknownPathCtx = {
|
|
24
|
+
method: "POST",
|
|
25
|
+
path: "/custom-endpoint",
|
|
26
|
+
headers: new Headers(),
|
|
27
|
+
} satisfies Partial<MatcherContext>;
|
|
28
|
+
|
|
29
|
+
expect(matcher(knownPathCtx as MatcherContext)).toBe(true);
|
|
30
|
+
expect(matcher(unknownPathCtx as MatcherContext)).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("rejects non-POST methods", () => {
|
|
34
|
+
const matcher = getPostRewriteMatcher();
|
|
35
|
+
type MatcherContext = Parameters<typeof matcher>[0];
|
|
36
|
+
|
|
37
|
+
const getSignInCtx = {
|
|
38
|
+
method: "GET",
|
|
39
|
+
path: "/sign-in/email",
|
|
40
|
+
headers: new Headers(),
|
|
41
|
+
} satisfies Partial<MatcherContext>;
|
|
42
|
+
const optionsLinkSocialCtx = {
|
|
43
|
+
method: "OPTIONS",
|
|
44
|
+
path: "/link-social",
|
|
45
|
+
headers: new Headers(),
|
|
46
|
+
} satisfies Partial<MatcherContext>;
|
|
47
|
+
|
|
48
|
+
expect(matcher(getSignInCtx as MatcherContext)).toBe(false);
|
|
49
|
+
expect(matcher(optionsLinkSocialCtx as MatcherContext)).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("rejects expo-native requests", () => {
|
|
53
|
+
const matcher = getPostRewriteMatcher();
|
|
54
|
+
type MatcherContext = Parameters<typeof matcher>[0];
|
|
55
|
+
|
|
56
|
+
const headers = new Headers();
|
|
57
|
+
headers.set("expo-origin", "expo");
|
|
58
|
+
|
|
59
|
+
const expoCtx = {
|
|
60
|
+
method: "POST",
|
|
61
|
+
path: "/sign-in/social",
|
|
62
|
+
headers,
|
|
63
|
+
} satisfies Partial<MatcherContext>;
|
|
64
|
+
|
|
65
|
+
expect(matcher(expoCtx as MatcherContext)).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { BetterAuthPlugin } from "better-auth";
|
|
2
2
|
import { setSessionCookie } from "better-auth/cookies";
|
|
3
3
|
import { generateRandomString } from "better-auth/crypto";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
createAuthMiddleware,
|
|
7
|
-
oneTimeToken as oneTimeTokenPlugin,
|
|
8
|
-
} from "better-auth/plugins";
|
|
4
|
+
import { createAuthEndpoint, createAuthMiddleware } from "better-auth/api";
|
|
5
|
+
import { oneTimeToken as oneTimeTokenPlugin } from "better-auth/plugins";
|
|
9
6
|
import { z } from "zod";
|
|
10
7
|
|
|
11
8
|
export const crossDomain = ({ siteUrl }: { siteUrl: string }) => {
|
|
@@ -86,9 +83,9 @@ export const crossDomain = ({ siteUrl }: { siteUrl: string }) => {
|
|
|
86
83
|
},
|
|
87
84
|
{
|
|
88
85
|
matcher: (ctx) => {
|
|
89
|
-
return (
|
|
86
|
+
return Boolean(
|
|
90
87
|
ctx.method === "GET" &&
|
|
91
|
-
ctx.path
|
|
88
|
+
ctx.path?.startsWith("/verify-email") &&
|
|
92
89
|
!isExpoNative(ctx)
|
|
93
90
|
);
|
|
94
91
|
},
|
|
@@ -101,26 +98,18 @@ export const crossDomain = ({ siteUrl }: { siteUrl: string }) => {
|
|
|
101
98
|
},
|
|
102
99
|
{
|
|
103
100
|
matcher: (ctx) => {
|
|
104
|
-
return (
|
|
105
|
-
((ctx.method === "POST" && ctx.path.startsWith("/link-social")) ||
|
|
106
|
-
ctx.path.startsWith("/send-verification-email") ||
|
|
107
|
-
ctx.path.startsWith("/sign-in/email") ||
|
|
108
|
-
ctx.path.startsWith("/sign-in/social") ||
|
|
109
|
-
ctx.path.startsWith("/sign-in/magic-link") ||
|
|
110
|
-
ctx.path.startsWith("/delete-user") ||
|
|
111
|
-
ctx.path.startsWith("/change-email")) &&
|
|
112
|
-
!isExpoNative(ctx)
|
|
113
|
-
);
|
|
101
|
+
return Boolean(ctx.method === "POST" && !isExpoNative(ctx));
|
|
114
102
|
},
|
|
115
103
|
handler: createAuthMiddleware(async (ctx) => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
104
|
+
if (ctx.body?.callbackURL) {
|
|
105
|
+
ctx.body.callbackURL = rewriteCallbackURL(ctx.body.callbackURL);
|
|
106
|
+
}
|
|
107
|
+
if (ctx.body?.newUserCallbackURL) {
|
|
119
108
|
ctx.body.newUserCallbackURL = rewriteCallbackURL(
|
|
120
109
|
ctx.body.newUserCallbackURL
|
|
121
110
|
);
|
|
122
111
|
}
|
|
123
|
-
if (
|
|
112
|
+
if (ctx.body?.errorCallbackURL) {
|
|
124
113
|
ctx.body.errorCallbackURL = rewriteCallbackURL(
|
|
125
114
|
ctx.body.errorCallbackURL
|
|
126
115
|
);
|
|
@@ -151,7 +140,7 @@ export const crossDomain = ({ siteUrl }: { siteUrl: string }) => {
|
|
|
151
140
|
},
|
|
152
141
|
{
|
|
153
142
|
matcher: (ctx) => {
|
|
154
|
-
return (
|
|
143
|
+
return Boolean(
|
|
155
144
|
(ctx.path?.startsWith("/callback") ||
|
|
156
145
|
ctx.path?.startsWith("/oauth2/callback") ||
|
|
157
146
|
ctx.path?.startsWith("/magic-link/verify")) &&
|
package/src/react-start/index.ts
CHANGED
|
@@ -89,6 +89,7 @@ export const convexBetterAuthReactStart = (
|
|
|
89
89
|
const mutableHeaders = new Headers(headers);
|
|
90
90
|
mutableHeaders.delete("content-length");
|
|
91
91
|
mutableHeaders.delete("transfer-encoding");
|
|
92
|
+
mutableHeaders.set("accept-encoding", "identity");
|
|
92
93
|
return getToken(siteUrl, mutableHeaders, opts);
|
|
93
94
|
});
|
|
94
95
|
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { Session, User } from "@better-auth/core/db";
|
|
2
|
+
import { createTestSuite } from "@better-auth/test-utils/adapter";
|
|
3
|
+
import { setCookieToHeader } from "better-auth/cookies";
|
|
4
|
+
import { expect } from "vitest";
|
|
5
|
+
|
|
6
|
+
export const AUTH_FLOW_DEFAULT_BETTER_AUTH_OPTIONS = {
|
|
7
|
+
emailAndPassword: {
|
|
8
|
+
enabled: true,
|
|
9
|
+
password: {
|
|
10
|
+
hash: async (password: string) => password,
|
|
11
|
+
async verify(data: { hash: string; password: string }) {
|
|
12
|
+
return data.hash === data.password;
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const getAuthFlowSuiteTests = (
|
|
19
|
+
{
|
|
20
|
+
generate,
|
|
21
|
+
getAuth,
|
|
22
|
+
modifyBetterAuthOptions,
|
|
23
|
+
tryCatch,
|
|
24
|
+
}: Parameters<Parameters<typeof createTestSuite>[2]>[0],
|
|
25
|
+
) => ({
|
|
26
|
+
"should successfully sign up": async () => {
|
|
27
|
+
const auth = await getAuth();
|
|
28
|
+
const user = await generate("user");
|
|
29
|
+
const result = await auth.api.signUpEmail({
|
|
30
|
+
body: {
|
|
31
|
+
email: user.email,
|
|
32
|
+
password: crypto.randomUUID(),
|
|
33
|
+
name: user.name,
|
|
34
|
+
image: user.image || "",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
expect(result.user).toBeDefined();
|
|
38
|
+
expect(result.user.email).toBe(user.email);
|
|
39
|
+
expect(result.user.name).toBe(user.name);
|
|
40
|
+
expect(result.user.image).toBe(user.image || "");
|
|
41
|
+
expect(result.user.emailVerified).toBe(false);
|
|
42
|
+
expect(result.user.createdAt).toBeDefined();
|
|
43
|
+
expect(result.user.updatedAt).toBeDefined();
|
|
44
|
+
},
|
|
45
|
+
"should successfully sign in": async () => {
|
|
46
|
+
const auth = await getAuth();
|
|
47
|
+
const user = await generate("user");
|
|
48
|
+
const password = crypto.randomUUID();
|
|
49
|
+
const signUpResult = await auth.api.signUpEmail({
|
|
50
|
+
body: {
|
|
51
|
+
email: user.email,
|
|
52
|
+
password: password,
|
|
53
|
+
name: user.name,
|
|
54
|
+
image: user.image || "",
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const result = await auth.api.signInEmail({
|
|
58
|
+
body: { email: user.email, password: password },
|
|
59
|
+
});
|
|
60
|
+
expect(result.user).toBeDefined();
|
|
61
|
+
expect(result.user.id).toBe(signUpResult.user.id);
|
|
62
|
+
},
|
|
63
|
+
"should successfully get session": async () => {
|
|
64
|
+
const auth = await getAuth();
|
|
65
|
+
const user = await generate("user");
|
|
66
|
+
const password = crypto.randomUUID();
|
|
67
|
+
const response = await auth.api.signUpEmail({
|
|
68
|
+
body: {
|
|
69
|
+
email: user.email,
|
|
70
|
+
password: password,
|
|
71
|
+
name: user.name,
|
|
72
|
+
image: user.image || "",
|
|
73
|
+
},
|
|
74
|
+
asResponse: true,
|
|
75
|
+
});
|
|
76
|
+
const headers = new Headers();
|
|
77
|
+
setCookieToHeader(headers)({ response });
|
|
78
|
+
const result = await auth.api.getSession({
|
|
79
|
+
headers,
|
|
80
|
+
});
|
|
81
|
+
const signUpResult = (await response.json()) as {
|
|
82
|
+
user: User;
|
|
83
|
+
session: Session;
|
|
84
|
+
};
|
|
85
|
+
signUpResult.user.createdAt = new Date(signUpResult.user.createdAt);
|
|
86
|
+
signUpResult.user.updatedAt = new Date(signUpResult.user.updatedAt);
|
|
87
|
+
expect(result?.user).toBeDefined();
|
|
88
|
+
expect(result?.user).toStrictEqual(signUpResult.user);
|
|
89
|
+
expect(result?.session).toBeDefined();
|
|
90
|
+
},
|
|
91
|
+
"should not sign in with invalid email": async () => {
|
|
92
|
+
const auth = await getAuth();
|
|
93
|
+
const user = await generate("user");
|
|
94
|
+
const { data, error } = await tryCatch(
|
|
95
|
+
auth.api.signInEmail({
|
|
96
|
+
body: { email: user.email, password: crypto.randomUUID() },
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
expect(data).toBeNull();
|
|
100
|
+
expect(error).toBeDefined();
|
|
101
|
+
},
|
|
102
|
+
"should store and retrieve timestamps correctly across timezones": async () => {
|
|
103
|
+
using _ = recoverProcessTZ();
|
|
104
|
+
const auth = await getAuth();
|
|
105
|
+
const user = await generate("user");
|
|
106
|
+
const password = crypto.randomUUID();
|
|
107
|
+
const userSignUp = await auth.api.signUpEmail({
|
|
108
|
+
body: {
|
|
109
|
+
email: user.email,
|
|
110
|
+
password: password,
|
|
111
|
+
name: user.name,
|
|
112
|
+
image: user.image || "",
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
process.env.TZ = "Europe/London";
|
|
116
|
+
const userSignIn = await auth.api.signInEmail({
|
|
117
|
+
body: { email: user.email, password: password },
|
|
118
|
+
});
|
|
119
|
+
process.env.TZ = "America/Los_Angeles";
|
|
120
|
+
expect(userSignUp.user.createdAt.toISOString()).toStrictEqual(
|
|
121
|
+
userSignIn.user.createdAt.toISOString(),
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
"should sign up with additional fields": async () => {
|
|
125
|
+
await modifyBetterAuthOptions(
|
|
126
|
+
{ user: { additionalFields: { dateField: { type: "date" } } } },
|
|
127
|
+
true,
|
|
128
|
+
);
|
|
129
|
+
const auth = await getAuth();
|
|
130
|
+
const user = await generate("user");
|
|
131
|
+
const dateField = new Date();
|
|
132
|
+
const response = await auth.api.signUpEmail({
|
|
133
|
+
body: {
|
|
134
|
+
email: user.email,
|
|
135
|
+
name: user.name,
|
|
136
|
+
password: crypto.randomUUID(),
|
|
137
|
+
//@ts-expect-error - we are testing with additional fields
|
|
138
|
+
dateField: dateField.toISOString(), // using iso string to simulate client to server communication (this should be converted back to Date)
|
|
139
|
+
},
|
|
140
|
+
asResponse: true,
|
|
141
|
+
});
|
|
142
|
+
const headers = new Headers();
|
|
143
|
+
setCookieToHeader(headers)({ response });
|
|
144
|
+
const result = await auth.api.getSession({
|
|
145
|
+
headers,
|
|
146
|
+
});
|
|
147
|
+
//@ts-expect-error - we are testing with additional fields
|
|
148
|
+
expect(result?.user.dateField).toStrictEqual(dateField);
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* This test suite tests basic authentication flow using the adapter.
|
|
154
|
+
*/
|
|
155
|
+
export const authFlowTestSuite = createTestSuite(
|
|
156
|
+
"auth-flow",
|
|
157
|
+
{
|
|
158
|
+
defaultBetterAuthOptions: AUTH_FLOW_DEFAULT_BETTER_AUTH_OPTIONS,
|
|
159
|
+
},
|
|
160
|
+
(helpers) => getAuthFlowSuiteTests(helpers),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
function recoverProcessTZ() {
|
|
164
|
+
const originalTZ = process.env.TZ;
|
|
165
|
+
return {
|
|
166
|
+
[Symbol.dispose]: () => {
|
|
167
|
+
process.env.TZ = originalTZ;
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|