faire-auth 1.0.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/LICENSE +661 -0
- package/README.md +34 -0
- package/dist/access-B5bBI4uT.mjs +39 -0
- package/dist/access-Crt-IJ2P.cjs +51 -0
- package/dist/adapter-factory-BXei1QRX.mjs +881 -0
- package/dist/adapter-factory-DT-_2aHJ.cjs +893 -0
- package/dist/adapters/drizzle-adapter/index.cjs +208 -0
- package/dist/adapters/drizzle-adapter/index.d.cts +48 -0
- package/dist/adapters/drizzle-adapter/index.d.mts +48 -0
- package/dist/adapters/drizzle-adapter/index.mjs +207 -0
- package/dist/adapters/index.cjs +23 -0
- package/dist/adapters/index.d.cts +157 -0
- package/dist/adapters/index.d.mts +157 -0
- package/dist/adapters/index.mjs +17 -0
- package/dist/adapters/kysely-adapter/index.cjs +11 -0
- package/dist/adapters/kysely-adapter/index.d.cts +52 -0
- package/dist/adapters/kysely-adapter/index.d.mts +52 -0
- package/dist/adapters/kysely-adapter/index.mjs +9 -0
- package/dist/adapters/memory-adapter/index.cjs +9 -0
- package/dist/adapters/memory-adapter/index.d.cts +15 -0
- package/dist/adapters/memory-adapter/index.d.mts +15 -0
- package/dist/adapters/memory-adapter/index.mjs +9 -0
- package/dist/adapters/mongodb-adapter/index.cjs +9 -0
- package/dist/adapters/mongodb-adapter/index.d.cts +4 -0
- package/dist/adapters/mongodb-adapter/index.d.mts +4 -0
- package/dist/adapters/mongodb-adapter/index.mjs +9 -0
- package/dist/adapters/prisma-adapter/index.cjs +156 -0
- package/dist/adapters/prisma-adapter/index.d.cts +35 -0
- package/dist/adapters/prisma-adapter/index.d.mts +35 -0
- package/dist/adapters/prisma-adapter/index.mjs +155 -0
- package/dist/adapters/test.cjs +797 -0
- package/dist/adapters/test.d.cts +82 -0
- package/dist/adapters/test.d.mts +82 -0
- package/dist/adapters/test.mjs +793 -0
- package/dist/api/index.cjs +20 -0
- package/dist/api/index.d.cts +3 -0
- package/dist/api/index.d.mts +3 -0
- package/dist/api/index.mjs +20 -0
- package/dist/api/middleware/index.cjs +16 -0
- package/dist/api/middleware/index.d.cts +16 -0
- package/dist/api/middleware/index.d.mts +16 -0
- package/dist/api/middleware/index.mjs +11 -0
- package/dist/api-Bm89BLgN.cjs +1899 -0
- package/dist/api-_B7qO28y.mjs +1892 -0
- package/dist/auth-Bo9PDt5j.cjs +739 -0
- package/dist/auth-Ds4AG4h4.mjs +709 -0
- package/dist/bearer-0SeEmaS4.mjs +54 -0
- package/dist/bearer-CHeREcGT.cjs +60 -0
- package/dist/bun-sqlite-dialect-CfkBo2v5.mjs +155 -0
- package/dist/bun-sqlite-dialect-wuaC2-gh.cjs +156 -0
- package/dist/chunk-Ceigfy4P.mjs +39 -0
- package/dist/chunk-oakRccI5.cjs +60 -0
- package/dist/client/index.cjs +22 -0
- package/dist/client/index.d.cts +8 -0
- package/dist/client/index.d.mts +8 -0
- package/dist/client/index.mjs +19 -0
- package/dist/client/lynx/index.cjs +79 -0
- package/dist/client/lynx/index.d.cts +156 -0
- package/dist/client/lynx/index.d.mts +156 -0
- package/dist/client/lynx/index.mjs +76 -0
- package/dist/client/plugins/index.cjs +11 -0
- package/dist/client/plugins/index.d.cts +17 -0
- package/dist/client/plugins/index.d.mts +17 -0
- package/dist/client/plugins/index.mjs +10 -0
- package/dist/client/react/index.cjs +79 -0
- package/dist/client/react/index.d.cts +156 -0
- package/dist/client/react/index.d.mts +156 -0
- package/dist/client/react/index.mjs +76 -0
- package/dist/client/solid/index.cjs +51 -0
- package/dist/client/solid/index.d.cts +90 -0
- package/dist/client/solid/index.d.mts +90 -0
- package/dist/client/solid/index.mjs +50 -0
- package/dist/client/svelte/index.cjs +28 -0
- package/dist/client/svelte/index.d.cts +110 -0
- package/dist/client/svelte/index.d.mts +110 -0
- package/dist/client/svelte/index.mjs +28 -0
- package/dist/client/vue/index.cjs +68 -0
- package/dist/client/vue/index.d.cts +123 -0
- package/dist/client/vue/index.d.mts +123 -0
- package/dist/client/vue/index.mjs +67 -0
- package/dist/cookies-B5xeA6i8.cjs +456 -0
- package/dist/cookies-Ch1JfQIz.mjs +367 -0
- package/dist/crypto/index.cjs +11 -0
- package/dist/crypto/index.d.cts +22 -0
- package/dist/crypto/index.d.mts +22 -0
- package/dist/crypto/index.mjs +5 -0
- package/dist/crypto-CcTxYH82.cjs +57 -0
- package/dist/crypto-CyQRFtkq.mjs +41 -0
- package/dist/db/index.cjs +40 -0
- package/dist/db/index.d.cts +4 -0
- package/dist/db/index.d.mts +4 -0
- package/dist/db/index.mjs +16 -0
- package/dist/db-BTKyYu-_.cjs +1180 -0
- package/dist/db-xiJtoDgz.mjs +1119 -0
- package/dist/defu-B0Svx_x4.cjs +34 -0
- package/dist/defu-SZkpHhbR.mjs +28 -0
- package/dist/email-verification-C-AsfJsb.cjs +247 -0
- package/dist/email-verification-CWhj2qfb.mjs +228 -0
- package/dist/hono-BEq1NYVX.cjs +526 -0
- package/dist/hono-Cdukwu5K.cjs +13 -0
- package/dist/hono-CoKYWnXA.mjs +7 -0
- package/dist/hono-Covz10jU.mjs +508 -0
- package/dist/hono-DOM31WQz.d.cts +18 -0
- package/dist/hono-DuE14mmj.d.mts +18 -0
- package/dist/index-B-WeOMzg.d.cts +13350 -0
- package/dist/index-B09P9p5_.d.cts +33 -0
- package/dist/index-B5_0QTLg.d.mts +3 -0
- package/dist/index-B7SKyR_a.d.cts +3 -0
- package/dist/index-BVHscLQl.d.cts +992 -0
- package/dist/index-C2-2QDyS.d.cts +35 -0
- package/dist/index-CTwrVluH.d.mts +41 -0
- package/dist/index-CWAqWfoZ.d.cts +27 -0
- package/dist/index-CYSShrFx.d.mts +27 -0
- package/dist/index-Qu-iJGNr.d.mts +992 -0
- package/dist/index-cs4Sh0En.d.cts +41 -0
- package/dist/index-jlessPI0.d.mts +13350 -0
- package/dist/index-ppgcFe12.d.mts +33 -0
- package/dist/index-to0RO38U.d.mts +35 -0
- package/dist/index.cjs +85 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +27 -0
- package/dist/integrations/next-js.cjs +50 -0
- package/dist/integrations/next-js.d.cts +23 -0
- package/dist/integrations/next-js.d.mts +23 -0
- package/dist/integrations/next-js.mjs +49 -0
- package/dist/integrations/node.cjs +139 -0
- package/dist/integrations/node.d.cts +22 -0
- package/dist/integrations/node.d.mts +22 -0
- package/dist/integrations/node.mjs +134 -0
- package/dist/integrations/react-start.cjs +37 -0
- package/dist/integrations/react-start.d.cts +17 -0
- package/dist/integrations/react-start.d.mts +17 -0
- package/dist/integrations/react-start.mjs +37 -0
- package/dist/integrations/solid-start.cjs +14 -0
- package/dist/integrations/solid-start.d.cts +13 -0
- package/dist/integrations/solid-start.d.mts +13 -0
- package/dist/integrations/solid-start.mjs +13 -0
- package/dist/integrations/svelte-kit.cjs +52 -0
- package/dist/integrations/svelte-kit.d.cts +42 -0
- package/dist/integrations/svelte-kit.d.mts +42 -0
- package/dist/integrations/svelte-kit.mjs +49 -0
- package/dist/ip-B5SwXaMB.cjs +54 -0
- package/dist/ip-BjNYspCH.mjs +36 -0
- package/dist/json-B1v2qRTQ.mjs +24 -0
- package/dist/json-CcJ2HjGo.cjs +30 -0
- package/dist/kysely-adapter-Bxi7sPdG.cjs +288 -0
- package/dist/kysely-adapter-DRuoT_X8.mjs +270 -0
- package/dist/logged-CyGfp8_H.mjs +187 -0
- package/dist/logged-DQK3C64b.cjs +193 -0
- package/dist/memory-adapter-BlnDIAAX.cjs +154 -0
- package/dist/memory-adapter-Db3tsJTn.mjs +148 -0
- package/dist/middleware-CE6OhDkq.mjs +29 -0
- package/dist/middleware-CWvRH4EW.cjs +47 -0
- package/dist/mongodb-adapter-C_qGQED5.mjs +291 -0
- package/dist/mongodb-adapter-C_qfK87x.cjs +297 -0
- package/dist/node-sqlite-dialect-BfBzyOAg.mjs +155 -0
- package/dist/node-sqlite-dialect-mJWC8LWQ.cjs +156 -0
- package/dist/oauth2/index.cjs +25 -0
- package/dist/oauth2/index.d.cts +42 -0
- package/dist/oauth2/index.d.mts +42 -0
- package/dist/oauth2/index.mjs +16 -0
- package/dist/oauth2-B8M0lW9l.mjs +159 -0
- package/dist/oauth2-BLeOEi7Y.cjs +177 -0
- package/dist/origin-check-8Gajklvh.mjs +228 -0
- package/dist/origin-check-id9lTnqZ.cjs +246 -0
- package/dist/parser-CdncAl9i.cjs +83 -0
- package/dist/parser-CeAer-RM.mjs +71 -0
- package/dist/passkey-B6N20LSS.cjs +512 -0
- package/dist/passkey-DJsR_GX3.mjs +505 -0
- package/dist/plugins/access/index.cjs +4 -0
- package/dist/plugins/access/index.d.cts +2 -0
- package/dist/plugins/access/index.d.mts +2 -0
- package/dist/plugins/access/index.mjs +3 -0
- package/dist/plugins/bearer/index.cjs +7 -0
- package/dist/plugins/bearer/index.d.cts +4 -0
- package/dist/plugins/bearer/index.d.mts +4 -0
- package/dist/plugins/bearer/index.mjs +7 -0
- package/dist/plugins/index.cjs +49 -0
- package/dist/plugins/index.d.cts +9326 -0
- package/dist/plugins/index.d.mts +9326 -0
- package/dist/plugins/index.mjs +26 -0
- package/dist/plugins/passkey/index.cjs +15 -0
- package/dist/plugins/passkey/index.d.cts +4 -0
- package/dist/plugins/passkey/index.d.mts +4 -0
- package/dist/plugins/passkey/index.mjs +15 -0
- package/dist/plugins-C1lm2Wj3.cjs +5254 -0
- package/dist/plugins-Dai1QkRU.mjs +5199 -0
- package/dist/request-1NL_1lyJ.mjs +58 -0
- package/dist/request-CPNlp-DK.cjs +100 -0
- package/dist/schema-D-qjygfE.cjs +179 -0
- package/dist/schema-DTIwLLmf.mjs +125 -0
- package/dist/session-De9POJTW.cjs +641 -0
- package/dist/session-rH8ougDl.mjs +538 -0
- package/dist/social-providers/index.cjs +10 -0
- package/dist/social-providers/index.d.cts +2 -0
- package/dist/social-providers/index.d.mts +2 -0
- package/dist/social-providers/index.mjs +5 -0
- package/dist/social-providers-DcFNUT0S.cjs +13 -0
- package/dist/social-providers-DoYJhBe3.mjs +9 -0
- package/dist/state--f7fwIGh.cjs +99 -0
- package/dist/state-CqJfCIl9.mjs +86 -0
- package/dist/test-utils/index.cjs +27492 -0
- package/dist/test-utils/index.d.cts +4584 -0
- package/dist/test-utils/index.d.mts +4584 -0
- package/dist/test-utils/index.mjs +27490 -0
- package/dist/types/index.cjs +0 -0
- package/dist/types/index.d.cts +3 -0
- package/dist/types/index.d.mts +3 -0
- package/dist/types/index.mjs +1 -0
- package/dist/url-BoUuoIwZ.mjs +88 -0
- package/dist/url-D2yvKaM7.cjs +118 -0
- package/dist/utils/cookies.cjs +51 -0
- package/dist/utils/cookies.d.cts +179 -0
- package/dist/utils/cookies.d.mts +179 -0
- package/dist/utils/cookies.mjs +7 -0
- package/dist/utils-44aDDP8f.cjs +2 -0
- package/dist/utils-D4vZd1-9.mjs +4 -0
- package/dist/vanilla-Bu2PmFzE.cjs +30 -0
- package/dist/vanilla-TfHqeiC7.mjs +25 -0
- package/package.json +470 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/utils/defu.ts
|
|
3
|
+
const isPlainObject = (value) => {
|
|
4
|
+
if (value === null || typeof value !== "object") return false;
|
|
5
|
+
const prototype = Object.getPrototypeOf(value);
|
|
6
|
+
if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) return false;
|
|
7
|
+
if (Symbol.iterator in value) return false;
|
|
8
|
+
if (Symbol.toStringTag in value) return Object.prototype.toString.call(value) === "[object Module]";
|
|
9
|
+
return true;
|
|
10
|
+
};
|
|
11
|
+
const _defu = (baseObject, defaults, namespace = ".", merger) => {
|
|
12
|
+
if (!isPlainObject(defaults)) return _defu(baseObject, {}, namespace, merger);
|
|
13
|
+
const object = Object.assign({}, defaults);
|
|
14
|
+
for (const key in baseObject) {
|
|
15
|
+
if (key === "__proto__" || key === "constructor") continue;
|
|
16
|
+
const value = baseObject[key];
|
|
17
|
+
if (value === null || value === void 0) continue;
|
|
18
|
+
if (merger?.(object, key, value, namespace) != null) continue;
|
|
19
|
+
if (Array.isArray(value) && Array.isArray(object[key])) object[key] = [...value, ...object[key]];
|
|
20
|
+
else if (isPlainObject(value) && isPlainObject(object[key])) object[key] = _defu(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
|
|
21
|
+
else object[key] = value;
|
|
22
|
+
}
|
|
23
|
+
return object;
|
|
24
|
+
};
|
|
25
|
+
const createDefu = (merger) => (...arguments_) => arguments_.reduce((p, c) => _defu(p, c, "", merger), {});
|
|
26
|
+
const defu = createDefu();
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
Object.defineProperty(exports, 'defu', {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get: function () {
|
|
32
|
+
return defu;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/utils/defu.ts
|
|
2
|
+
const isPlainObject = (value) => {
|
|
3
|
+
if (value === null || typeof value !== "object") return false;
|
|
4
|
+
const prototype = Object.getPrototypeOf(value);
|
|
5
|
+
if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) return false;
|
|
6
|
+
if (Symbol.iterator in value) return false;
|
|
7
|
+
if (Symbol.toStringTag in value) return Object.prototype.toString.call(value) === "[object Module]";
|
|
8
|
+
return true;
|
|
9
|
+
};
|
|
10
|
+
const _defu = (baseObject, defaults, namespace = ".", merger) => {
|
|
11
|
+
if (!isPlainObject(defaults)) return _defu(baseObject, {}, namespace, merger);
|
|
12
|
+
const object = Object.assign({}, defaults);
|
|
13
|
+
for (const key in baseObject) {
|
|
14
|
+
if (key === "__proto__" || key === "constructor") continue;
|
|
15
|
+
const value = baseObject[key];
|
|
16
|
+
if (value === null || value === void 0) continue;
|
|
17
|
+
if (merger?.(object, key, value, namespace) != null) continue;
|
|
18
|
+
if (Array.isArray(value) && Array.isArray(object[key])) object[key] = [...value, ...object[key]];
|
|
19
|
+
else if (isPlainObject(value) && isPlainObject(object[key])) object[key] = _defu(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
|
|
20
|
+
else object[key] = value;
|
|
21
|
+
}
|
|
22
|
+
return object;
|
|
23
|
+
};
|
|
24
|
+
const createDefu = (merger) => (...arguments_) => arguments_.reduce((p, c) => _defu(p, c, "", merger), {});
|
|
25
|
+
const defu = createDefu();
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
export { defu as t };
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
const require_chunk = require('./chunk-oakRccI5.cjs');
|
|
2
|
+
const require_crypto = require('./crypto-CcTxYH82.cjs');
|
|
3
|
+
const require_cookies = require('./cookies-B5xeA6i8.cjs');
|
|
4
|
+
const require_middleware = require('./middleware-CWvRH4EW.cjs');
|
|
5
|
+
const require_session = require('./session-De9POJTW.cjs');
|
|
6
|
+
const require_origin_check = require('./origin-check-id9lTnqZ.cjs');
|
|
7
|
+
let __faire_auth_core_factory = require("@faire-auth/core/factory");
|
|
8
|
+
let __faire_auth_core_static = require("@faire-auth/core/static");
|
|
9
|
+
let __faire_auth_core_utils = require("@faire-auth/core/utils");
|
|
10
|
+
let zod = require("zod");
|
|
11
|
+
zod = require_chunk.__toESM(zod);
|
|
12
|
+
let jose = require("jose");
|
|
13
|
+
let jose_errors = require("jose/errors");
|
|
14
|
+
|
|
15
|
+
//#region src/api/schema/email-verification.ts
|
|
16
|
+
const sendVerificationEmailSchema = zod.object({
|
|
17
|
+
email: __faire_auth_core_factory.emailSchema.openapi({ description: "The email to send the verification email to" }),
|
|
18
|
+
callbackURL: (0, __faire_auth_core_factory.callbackURLSchema)(true).openapi({ description: "The URL to use for email verification callback" })
|
|
19
|
+
});
|
|
20
|
+
const verifyEmailQuerySchema = zod.object({
|
|
21
|
+
token: zod.string().openapi({ description: "The token to verify the email" }),
|
|
22
|
+
callbackURL: (0, __faire_auth_core_factory.callbackURLSchema)(true).openapi({ description: "The URL to redirect to after email verification" })
|
|
23
|
+
});
|
|
24
|
+
const verifyEmailTokenSchema = zod.object({
|
|
25
|
+
email: __faire_auth_core_factory.emailSchema,
|
|
26
|
+
updateTo: zod.string().optional()
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/api/middleware/token-check.ts
|
|
31
|
+
const onError = async (ctx, error) => {
|
|
32
|
+
let code;
|
|
33
|
+
if (error === "missing_token") code = 400;
|
|
34
|
+
else code = 401;
|
|
35
|
+
const url = ctx.req.query("callbackURL");
|
|
36
|
+
if (url) {
|
|
37
|
+
if (url.includes("?")) return ctx.redirect(`${url}&error=${error}`, 302);
|
|
38
|
+
return ctx.redirect(`${url}?error=${error}`, 302);
|
|
39
|
+
}
|
|
40
|
+
return ctx.render({
|
|
41
|
+
success: __faire_auth_core_static.False,
|
|
42
|
+
code: error.toUpperCase(),
|
|
43
|
+
message: (0, __faire_auth_core_utils.capitalizeFirstLetter)(error.replaceAll("_", " "))
|
|
44
|
+
}, code);
|
|
45
|
+
};
|
|
46
|
+
const verifyToken = async (token, context) => {
|
|
47
|
+
let jwt;
|
|
48
|
+
try {
|
|
49
|
+
jwt = await (0, jose.jwtVerify)(token, new TextEncoder().encode(context.secret), { algorithms: ["HS256"] });
|
|
50
|
+
} catch (e) {
|
|
51
|
+
if (e instanceof jose_errors.JWTExpired) return "token_expired";
|
|
52
|
+
return "invalid_token";
|
|
53
|
+
}
|
|
54
|
+
return jwt;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Validates token against context secret.
|
|
58
|
+
* @template V - The context variables type.
|
|
59
|
+
* @param getValue - Function to get the token from the context.
|
|
60
|
+
* @returns The middleware function.
|
|
61
|
+
*/
|
|
62
|
+
const tokenCheck = (getValue, schema) => require_middleware.createMiddleware()(async (ctx, next) => {
|
|
63
|
+
const token = await getValue(ctx);
|
|
64
|
+
if (!token) return onError(ctx, "missing_token");
|
|
65
|
+
const res$1 = await verifyToken(token, ctx.get("context"));
|
|
66
|
+
if (typeof res$1 === "string") return onError(ctx, res$1);
|
|
67
|
+
const dat = await schema.safeParseAsync(res$1.payload);
|
|
68
|
+
if (dat.success === false) return onError(ctx, "invalid_token");
|
|
69
|
+
ctx.set("token", dat.data);
|
|
70
|
+
return await next();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/api/routes/email-verification.ts
|
|
75
|
+
const createEmailVerificationToken = async (secret, email, updateTo, expiresIn = 3600) => {
|
|
76
|
+
return await (0, require_crypto.crypto_exports.signJWT)({
|
|
77
|
+
email: email.toLowerCase(),
|
|
78
|
+
updateTo
|
|
79
|
+
}, secret, expiresIn);
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* A function to send a verification email to the user
|
|
83
|
+
*/
|
|
84
|
+
const sendVerificationEmailFn = async (ctx, user, callbackURL = encodeURIComponent("/"), options) => {
|
|
85
|
+
const context = ctx.get("context");
|
|
86
|
+
if (!options?.emailVerification?.sendVerificationEmail) {
|
|
87
|
+
context.logger.error("Verification email isn't enabled.");
|
|
88
|
+
return ctx.render({
|
|
89
|
+
success: __faire_auth_core_static.False,
|
|
90
|
+
message: "Verification email isn't enabled"
|
|
91
|
+
}, 400);
|
|
92
|
+
}
|
|
93
|
+
const token = await createEmailVerificationToken(context.secret, user.email, void 0, options.emailVerification.expiresIn);
|
|
94
|
+
const url = `${context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;
|
|
95
|
+
await options.emailVerification.sendVerificationEmail({
|
|
96
|
+
user,
|
|
97
|
+
url,
|
|
98
|
+
token
|
|
99
|
+
}, ctx);
|
|
100
|
+
};
|
|
101
|
+
const sendVerificationEmailRoute = (0, __faire_auth_core_factory.createRoute)({
|
|
102
|
+
operationId: __faire_auth_core_static.Routes.SEND_VERIFICATION_EMAIL,
|
|
103
|
+
method: "post",
|
|
104
|
+
path: "/send-verification-email",
|
|
105
|
+
description: "Send a verification email to the user",
|
|
106
|
+
request: (0, __faire_auth_core_factory.req)().bdy(sendVerificationEmailSchema).bld(),
|
|
107
|
+
responses: (0, __faire_auth_core_factory.res)(__faire_auth_core_static.SCHEMAS[__faire_auth_core_static.Definitions.SUCCESS].default).err(400).zod().bld()
|
|
108
|
+
});
|
|
109
|
+
const sendVerificationEmail = require_session.createEndpoint(sendVerificationEmailRoute, (options) => async (ctx) => {
|
|
110
|
+
const context = ctx.get("context");
|
|
111
|
+
if (!options.emailVerification?.sendVerificationEmail) {
|
|
112
|
+
context.logger.error("Verification email isn't enabled.");
|
|
113
|
+
return ctx.render({
|
|
114
|
+
success: __faire_auth_core_static.False,
|
|
115
|
+
message: "Verification email isn't enabled"
|
|
116
|
+
}, 400);
|
|
117
|
+
}
|
|
118
|
+
const { email, callbackURL } = ctx.req.valid("json");
|
|
119
|
+
const session = await require_session.getSessionFromCtx(ctx);
|
|
120
|
+
if (session instanceof Response) {
|
|
121
|
+
const user = await context.internalAdapter.findUserByEmail(email);
|
|
122
|
+
if (!user) return ctx.render({ success: __faire_auth_core_static.True }, 200);
|
|
123
|
+
await sendVerificationEmailFn(ctx, user.user, callbackURL, options);
|
|
124
|
+
return ctx.render({ success: __faire_auth_core_static.True }, 200);
|
|
125
|
+
}
|
|
126
|
+
if (session.user.emailVerified) return ctx.render({
|
|
127
|
+
success: __faire_auth_core_static.False,
|
|
128
|
+
message: "You can only send a verification email to an unverified email"
|
|
129
|
+
}, 400);
|
|
130
|
+
if (session.user.email !== email) return ctx.render({
|
|
131
|
+
success: __faire_auth_core_static.False,
|
|
132
|
+
message: "You can only send a verification email to your own email"
|
|
133
|
+
}, 400);
|
|
134
|
+
await sendVerificationEmailFn(ctx, session.user, callbackURL, options);
|
|
135
|
+
return ctx.render({ success: __faire_auth_core_static.True }, 200);
|
|
136
|
+
});
|
|
137
|
+
const verifyEmailRoute = (0, __faire_auth_core_factory.createRoute)({
|
|
138
|
+
operationId: __faire_auth_core_static.Routes.VERIFY_EMAIL,
|
|
139
|
+
method: "get",
|
|
140
|
+
path: "/verify-email",
|
|
141
|
+
description: "Verify the email of the user",
|
|
142
|
+
middleware: [require_origin_check.originCheck((ctx) => ctx.req.query("callbackURL")), tokenCheck((ctx) => ctx.req.query("token"), verifyEmailTokenSchema)],
|
|
143
|
+
request: (0, __faire_auth_core_factory.req)().qry(verifyEmailQuerySchema).bld(),
|
|
144
|
+
responses: (0, __faire_auth_core_factory.res)(__faire_auth_core_static.SCHEMAS[__faire_auth_core_static.Definitions.TOKEN_USER].default).err(401, "Invalid or expired token").err(500).rdr("Redirect to callback URL").zod().bld()
|
|
145
|
+
});
|
|
146
|
+
const verifyEmail = require_session.createEndpoint(verifyEmailRoute, (options) => async (ctx) => {
|
|
147
|
+
const { callbackURL } = ctx.req.valid("query");
|
|
148
|
+
const context = ctx.get("context");
|
|
149
|
+
const parsed = ctx.get("token");
|
|
150
|
+
const redirectOnError = (error) => {
|
|
151
|
+
if (callbackURL) {
|
|
152
|
+
if (callbackURL.includes("?")) return ctx.redirect(`${callbackURL}&error=${error}`, 302);
|
|
153
|
+
return ctx.redirect(`${callbackURL}?error=${error}`, 302);
|
|
154
|
+
}
|
|
155
|
+
return ctx.render({
|
|
156
|
+
success: __faire_auth_core_static.False,
|
|
157
|
+
code: error.toUpperCase(),
|
|
158
|
+
message: (0, __faire_auth_core_utils.capitalizeFirstLetter)(error.replaceAll("_", " "))
|
|
159
|
+
}, 401);
|
|
160
|
+
};
|
|
161
|
+
const user = await context.internalAdapter.findUserByEmail(parsed.email);
|
|
162
|
+
if (!user) return redirectOnError("user_not_found");
|
|
163
|
+
if (parsed.updateTo) {
|
|
164
|
+
const session = await require_session.getSessionFromCtx(ctx);
|
|
165
|
+
if (session instanceof Response || session.user.email !== parsed.email) return redirectOnError("unauthorized");
|
|
166
|
+
const updatedUser$1 = await context.internalAdapter.updateUserByEmail(parsed.email, {
|
|
167
|
+
email: parsed.updateTo,
|
|
168
|
+
emailVerified: false
|
|
169
|
+
});
|
|
170
|
+
if (updatedUser$1 == null) return ctx.render({
|
|
171
|
+
success: __faire_auth_core_static.False,
|
|
172
|
+
message: "Failed to update user"
|
|
173
|
+
}, 500);
|
|
174
|
+
const newToken = await createEmailVerificationToken(context.secret, parsed.updateTo);
|
|
175
|
+
if (options.emailVerification?.sendVerificationEmail) await options.emailVerification.sendVerificationEmail({
|
|
176
|
+
user: updatedUser$1,
|
|
177
|
+
url: `${context.baseURL}/verify-email?token=${newToken}&callbackURL=${callbackURL ?? encodeURIComponent("/")}`,
|
|
178
|
+
token: newToken
|
|
179
|
+
}, ctx);
|
|
180
|
+
await require_cookies.setSessionCookie(ctx, options, {
|
|
181
|
+
session: session.session,
|
|
182
|
+
user: {
|
|
183
|
+
...session.user,
|
|
184
|
+
email: parsed.updateTo,
|
|
185
|
+
emailVerified: false
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
if (callbackURL != null) return ctx.redirect(callbackURL, 302);
|
|
189
|
+
return ctx.render({
|
|
190
|
+
success: __faire_auth_core_static.True,
|
|
191
|
+
token: session.session.token,
|
|
192
|
+
user: updatedUser$1
|
|
193
|
+
}, 200);
|
|
194
|
+
}
|
|
195
|
+
if (options.emailVerification?.onEmailVerification) await options.emailVerification.onEmailVerification(user.user, ctx.req);
|
|
196
|
+
const updatedUser = await context.internalAdapter.updateUserByEmail(parsed.email, { emailVerified: true });
|
|
197
|
+
if (updatedUser == null) return ctx.render({
|
|
198
|
+
success: __faire_auth_core_static.False,
|
|
199
|
+
message: "Failed to update user"
|
|
200
|
+
}, 500);
|
|
201
|
+
if (options.emailVerification?.afterEmailVerification) await options.emailVerification.afterEmailVerification(updatedUser, ctx.req);
|
|
202
|
+
if (options.emailVerification?.autoSignInAfterVerification === true) {
|
|
203
|
+
const currentSession = await require_session.getSessionFromCtx(ctx);
|
|
204
|
+
if (currentSession instanceof Response || currentSession.user.email !== parsed.email) {
|
|
205
|
+
const session = await context.internalAdapter.createSession(user.user.id);
|
|
206
|
+
if (session == null) return ctx.render({
|
|
207
|
+
success: __faire_auth_core_static.False,
|
|
208
|
+
message: "Failed to create session"
|
|
209
|
+
}, 500);
|
|
210
|
+
await require_cookies.setSessionCookie(ctx, options, {
|
|
211
|
+
session,
|
|
212
|
+
user: {
|
|
213
|
+
...user.user,
|
|
214
|
+
emailVerified: true
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
} else await require_cookies.setSessionCookie(ctx, options, {
|
|
218
|
+
session: currentSession.session,
|
|
219
|
+
user: {
|
|
220
|
+
...currentSession.user,
|
|
221
|
+
emailVerified: true
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (callbackURL != null) return ctx.redirect(callbackURL, 302);
|
|
226
|
+
return ctx.render({ success: __faire_auth_core_static.False }, 200);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
//#endregion
|
|
230
|
+
Object.defineProperty(exports, 'createEmailVerificationToken', {
|
|
231
|
+
enumerable: true,
|
|
232
|
+
get: function () {
|
|
233
|
+
return createEmailVerificationToken;
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
Object.defineProperty(exports, 'sendVerificationEmail', {
|
|
237
|
+
enumerable: true,
|
|
238
|
+
get: function () {
|
|
239
|
+
return sendVerificationEmail;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
Object.defineProperty(exports, 'verifyEmail', {
|
|
243
|
+
enumerable: true,
|
|
244
|
+
get: function () {
|
|
245
|
+
return verifyEmail;
|
|
246
|
+
}
|
|
247
|
+
});
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { n as crypto_exports } from "./crypto-CyQRFtkq.mjs";
|
|
2
|
+
import { y as setSessionCookie } from "./cookies-Ch1JfQIz.mjs";
|
|
3
|
+
import { r as createMiddleware } from "./middleware-CE6OhDkq.mjs";
|
|
4
|
+
import { f as createEndpoint, r as getSessionFromCtx } from "./session-rH8ougDl.mjs";
|
|
5
|
+
import { n as originCheck } from "./origin-check-8Gajklvh.mjs";
|
|
6
|
+
import { callbackURLSchema, createRoute, emailSchema, req, res } from "@faire-auth/core/factory";
|
|
7
|
+
import { Definitions, False, Routes, SCHEMAS, True } from "@faire-auth/core/static";
|
|
8
|
+
import { capitalizeFirstLetter } from "@faire-auth/core/utils";
|
|
9
|
+
import * as z$1 from "zod";
|
|
10
|
+
import { jwtVerify } from "jose";
|
|
11
|
+
import { JWTExpired } from "jose/errors";
|
|
12
|
+
|
|
13
|
+
//#region src/api/schema/email-verification.ts
|
|
14
|
+
const sendVerificationEmailSchema = z$1.object({
|
|
15
|
+
email: emailSchema.openapi({ description: "The email to send the verification email to" }),
|
|
16
|
+
callbackURL: callbackURLSchema(true).openapi({ description: "The URL to use for email verification callback" })
|
|
17
|
+
});
|
|
18
|
+
const verifyEmailQuerySchema = z$1.object({
|
|
19
|
+
token: z$1.string().openapi({ description: "The token to verify the email" }),
|
|
20
|
+
callbackURL: callbackURLSchema(true).openapi({ description: "The URL to redirect to after email verification" })
|
|
21
|
+
});
|
|
22
|
+
const verifyEmailTokenSchema = z$1.object({
|
|
23
|
+
email: emailSchema,
|
|
24
|
+
updateTo: z$1.string().optional()
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/api/middleware/token-check.ts
|
|
29
|
+
const onError = async (ctx, error) => {
|
|
30
|
+
let code;
|
|
31
|
+
if (error === "missing_token") code = 400;
|
|
32
|
+
else code = 401;
|
|
33
|
+
const url = ctx.req.query("callbackURL");
|
|
34
|
+
if (url) {
|
|
35
|
+
if (url.includes("?")) return ctx.redirect(`${url}&error=${error}`, 302);
|
|
36
|
+
return ctx.redirect(`${url}?error=${error}`, 302);
|
|
37
|
+
}
|
|
38
|
+
return ctx.render({
|
|
39
|
+
success: False,
|
|
40
|
+
code: error.toUpperCase(),
|
|
41
|
+
message: capitalizeFirstLetter(error.replaceAll("_", " "))
|
|
42
|
+
}, code);
|
|
43
|
+
};
|
|
44
|
+
const verifyToken = async (token, context) => {
|
|
45
|
+
let jwt;
|
|
46
|
+
try {
|
|
47
|
+
jwt = await jwtVerify(token, new TextEncoder().encode(context.secret), { algorithms: ["HS256"] });
|
|
48
|
+
} catch (e) {
|
|
49
|
+
if (e instanceof JWTExpired) return "token_expired";
|
|
50
|
+
return "invalid_token";
|
|
51
|
+
}
|
|
52
|
+
return jwt;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Validates token against context secret.
|
|
56
|
+
* @template V - The context variables type.
|
|
57
|
+
* @param getValue - Function to get the token from the context.
|
|
58
|
+
* @returns The middleware function.
|
|
59
|
+
*/
|
|
60
|
+
const tokenCheck = (getValue, schema) => createMiddleware()(async (ctx, next) => {
|
|
61
|
+
const token = await getValue(ctx);
|
|
62
|
+
if (!token) return onError(ctx, "missing_token");
|
|
63
|
+
const res$1 = await verifyToken(token, ctx.get("context"));
|
|
64
|
+
if (typeof res$1 === "string") return onError(ctx, res$1);
|
|
65
|
+
const dat = await schema.safeParseAsync(res$1.payload);
|
|
66
|
+
if (dat.success === false) return onError(ctx, "invalid_token");
|
|
67
|
+
ctx.set("token", dat.data);
|
|
68
|
+
return await next();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/api/routes/email-verification.ts
|
|
73
|
+
const createEmailVerificationToken = async (secret, email, updateTo, expiresIn = 3600) => {
|
|
74
|
+
return await (0, crypto_exports.signJWT)({
|
|
75
|
+
email: email.toLowerCase(),
|
|
76
|
+
updateTo
|
|
77
|
+
}, secret, expiresIn);
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* A function to send a verification email to the user
|
|
81
|
+
*/
|
|
82
|
+
const sendVerificationEmailFn = async (ctx, user, callbackURL = encodeURIComponent("/"), options) => {
|
|
83
|
+
const context = ctx.get("context");
|
|
84
|
+
if (!options?.emailVerification?.sendVerificationEmail) {
|
|
85
|
+
context.logger.error("Verification email isn't enabled.");
|
|
86
|
+
return ctx.render({
|
|
87
|
+
success: False,
|
|
88
|
+
message: "Verification email isn't enabled"
|
|
89
|
+
}, 400);
|
|
90
|
+
}
|
|
91
|
+
const token = await createEmailVerificationToken(context.secret, user.email, void 0, options.emailVerification.expiresIn);
|
|
92
|
+
const url = `${context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;
|
|
93
|
+
await options.emailVerification.sendVerificationEmail({
|
|
94
|
+
user,
|
|
95
|
+
url,
|
|
96
|
+
token
|
|
97
|
+
}, ctx);
|
|
98
|
+
};
|
|
99
|
+
const sendVerificationEmailRoute = createRoute({
|
|
100
|
+
operationId: Routes.SEND_VERIFICATION_EMAIL,
|
|
101
|
+
method: "post",
|
|
102
|
+
path: "/send-verification-email",
|
|
103
|
+
description: "Send a verification email to the user",
|
|
104
|
+
request: req().bdy(sendVerificationEmailSchema).bld(),
|
|
105
|
+
responses: res(SCHEMAS[Definitions.SUCCESS].default).err(400).zod().bld()
|
|
106
|
+
});
|
|
107
|
+
const sendVerificationEmail = createEndpoint(sendVerificationEmailRoute, (options) => async (ctx) => {
|
|
108
|
+
const context = ctx.get("context");
|
|
109
|
+
if (!options.emailVerification?.sendVerificationEmail) {
|
|
110
|
+
context.logger.error("Verification email isn't enabled.");
|
|
111
|
+
return ctx.render({
|
|
112
|
+
success: False,
|
|
113
|
+
message: "Verification email isn't enabled"
|
|
114
|
+
}, 400);
|
|
115
|
+
}
|
|
116
|
+
const { email, callbackURL } = ctx.req.valid("json");
|
|
117
|
+
const session = await getSessionFromCtx(ctx);
|
|
118
|
+
if (session instanceof Response) {
|
|
119
|
+
const user = await context.internalAdapter.findUserByEmail(email);
|
|
120
|
+
if (!user) return ctx.render({ success: True }, 200);
|
|
121
|
+
await sendVerificationEmailFn(ctx, user.user, callbackURL, options);
|
|
122
|
+
return ctx.render({ success: True }, 200);
|
|
123
|
+
}
|
|
124
|
+
if (session.user.emailVerified) return ctx.render({
|
|
125
|
+
success: False,
|
|
126
|
+
message: "You can only send a verification email to an unverified email"
|
|
127
|
+
}, 400);
|
|
128
|
+
if (session.user.email !== email) return ctx.render({
|
|
129
|
+
success: False,
|
|
130
|
+
message: "You can only send a verification email to your own email"
|
|
131
|
+
}, 400);
|
|
132
|
+
await sendVerificationEmailFn(ctx, session.user, callbackURL, options);
|
|
133
|
+
return ctx.render({ success: True }, 200);
|
|
134
|
+
});
|
|
135
|
+
const verifyEmailRoute = createRoute({
|
|
136
|
+
operationId: Routes.VERIFY_EMAIL,
|
|
137
|
+
method: "get",
|
|
138
|
+
path: "/verify-email",
|
|
139
|
+
description: "Verify the email of the user",
|
|
140
|
+
middleware: [originCheck((ctx) => ctx.req.query("callbackURL")), tokenCheck((ctx) => ctx.req.query("token"), verifyEmailTokenSchema)],
|
|
141
|
+
request: req().qry(verifyEmailQuerySchema).bld(),
|
|
142
|
+
responses: res(SCHEMAS[Definitions.TOKEN_USER].default).err(401, "Invalid or expired token").err(500).rdr("Redirect to callback URL").zod().bld()
|
|
143
|
+
});
|
|
144
|
+
const verifyEmail = createEndpoint(verifyEmailRoute, (options) => async (ctx) => {
|
|
145
|
+
const { callbackURL } = ctx.req.valid("query");
|
|
146
|
+
const context = ctx.get("context");
|
|
147
|
+
const parsed = ctx.get("token");
|
|
148
|
+
const redirectOnError = (error) => {
|
|
149
|
+
if (callbackURL) {
|
|
150
|
+
if (callbackURL.includes("?")) return ctx.redirect(`${callbackURL}&error=${error}`, 302);
|
|
151
|
+
return ctx.redirect(`${callbackURL}?error=${error}`, 302);
|
|
152
|
+
}
|
|
153
|
+
return ctx.render({
|
|
154
|
+
success: False,
|
|
155
|
+
code: error.toUpperCase(),
|
|
156
|
+
message: capitalizeFirstLetter(error.replaceAll("_", " "))
|
|
157
|
+
}, 401);
|
|
158
|
+
};
|
|
159
|
+
const user = await context.internalAdapter.findUserByEmail(parsed.email);
|
|
160
|
+
if (!user) return redirectOnError("user_not_found");
|
|
161
|
+
if (parsed.updateTo) {
|
|
162
|
+
const session = await getSessionFromCtx(ctx);
|
|
163
|
+
if (session instanceof Response || session.user.email !== parsed.email) return redirectOnError("unauthorized");
|
|
164
|
+
const updatedUser$1 = await context.internalAdapter.updateUserByEmail(parsed.email, {
|
|
165
|
+
email: parsed.updateTo,
|
|
166
|
+
emailVerified: false
|
|
167
|
+
});
|
|
168
|
+
if (updatedUser$1 == null) return ctx.render({
|
|
169
|
+
success: False,
|
|
170
|
+
message: "Failed to update user"
|
|
171
|
+
}, 500);
|
|
172
|
+
const newToken = await createEmailVerificationToken(context.secret, parsed.updateTo);
|
|
173
|
+
if (options.emailVerification?.sendVerificationEmail) await options.emailVerification.sendVerificationEmail({
|
|
174
|
+
user: updatedUser$1,
|
|
175
|
+
url: `${context.baseURL}/verify-email?token=${newToken}&callbackURL=${callbackURL ?? encodeURIComponent("/")}`,
|
|
176
|
+
token: newToken
|
|
177
|
+
}, ctx);
|
|
178
|
+
await setSessionCookie(ctx, options, {
|
|
179
|
+
session: session.session,
|
|
180
|
+
user: {
|
|
181
|
+
...session.user,
|
|
182
|
+
email: parsed.updateTo,
|
|
183
|
+
emailVerified: false
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
if (callbackURL != null) return ctx.redirect(callbackURL, 302);
|
|
187
|
+
return ctx.render({
|
|
188
|
+
success: True,
|
|
189
|
+
token: session.session.token,
|
|
190
|
+
user: updatedUser$1
|
|
191
|
+
}, 200);
|
|
192
|
+
}
|
|
193
|
+
if (options.emailVerification?.onEmailVerification) await options.emailVerification.onEmailVerification(user.user, ctx.req);
|
|
194
|
+
const updatedUser = await context.internalAdapter.updateUserByEmail(parsed.email, { emailVerified: true });
|
|
195
|
+
if (updatedUser == null) return ctx.render({
|
|
196
|
+
success: False,
|
|
197
|
+
message: "Failed to update user"
|
|
198
|
+
}, 500);
|
|
199
|
+
if (options.emailVerification?.afterEmailVerification) await options.emailVerification.afterEmailVerification(updatedUser, ctx.req);
|
|
200
|
+
if (options.emailVerification?.autoSignInAfterVerification === true) {
|
|
201
|
+
const currentSession = await getSessionFromCtx(ctx);
|
|
202
|
+
if (currentSession instanceof Response || currentSession.user.email !== parsed.email) {
|
|
203
|
+
const session = await context.internalAdapter.createSession(user.user.id);
|
|
204
|
+
if (session == null) return ctx.render({
|
|
205
|
+
success: False,
|
|
206
|
+
message: "Failed to create session"
|
|
207
|
+
}, 500);
|
|
208
|
+
await setSessionCookie(ctx, options, {
|
|
209
|
+
session,
|
|
210
|
+
user: {
|
|
211
|
+
...user.user,
|
|
212
|
+
emailVerified: true
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
} else await setSessionCookie(ctx, options, {
|
|
216
|
+
session: currentSession.session,
|
|
217
|
+
user: {
|
|
218
|
+
...currentSession.user,
|
|
219
|
+
emailVerified: true
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
if (callbackURL != null) return ctx.redirect(callbackURL, 302);
|
|
224
|
+
return ctx.render({ success: False }, 200);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
//#endregion
|
|
228
|
+
export { sendVerificationEmail as n, verifyEmail as r, createEmailVerificationToken as t };
|