@baseplate-dev/plugin-auth 0.6.14 → 0.6.16
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/CHANGELOG.md +42 -0
- package/dist/auth/core/components/auth-definition-editor.js +3 -0
- package/dist/auth/core/components/role-editor-form/role-editor-form.js +2 -0
- package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/admin-crud-manage-roles-action.generator.d.ts +14 -28
- package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/generated/index.d.ts +14 -28
- package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/generated/template-renderers.d.ts +7 -14
- package/dist/better-auth/admin/generators/admin-crud-manage-roles-action/generated/typed-templates.d.ts +7 -14
- package/dist/better-auth/admin/generators/admin-crud-reset-password-action/admin-crud-reset-password-action.generator.d.ts +14 -28
- package/dist/better-auth/admin/generators/admin-crud-reset-password-action/generated/index.d.ts +14 -28
- package/dist/better-auth/admin/generators/admin-crud-reset-password-action/generated/template-renderers.d.ts +7 -14
- package/dist/better-auth/admin/generators/admin-crud-reset-password-action/generated/typed-templates.d.ts +14 -28
- package/dist/better-auth/admin/generators/admin-crud-roles-column/admin-crud-roles-column.generator.d.ts +7 -14
- package/dist/better-auth/generators/fastify/better-auth-module/better-auth-module.generator.d.ts +9 -2
- package/dist/better-auth/generators/fastify/better-auth-module/better-auth-module.generator.js +6 -2
- package/dist/better-auth/generators/fastify/better-auth-module/generated/index.d.ts +16 -2
- package/dist/better-auth/generators/fastify/better-auth-module/generated/template-renderers.d.ts +8 -1
- package/dist/better-auth/generators/fastify/better-auth-module/generated/typed-templates.d.ts +8 -1
- package/dist/better-auth/generators/fastify/better-auth-module/templates/module/services/auth.ts +5 -1
- package/dist/better-auth/generators/fastify/seed-initial-user/seed-initial-user.generator.js +4 -0
- package/dist/better-auth/generators/fastify/seed-initial-user/templates/src/prisma/seed-initial-user.ts +3 -2
- package/dist/better-auth/generators/react/better-auth-pages/better-auth-pages.generator.d.ts +7 -14
- package/dist/better-auth/generators/react/better-auth-pages/generated/index.d.ts +42 -84
- package/dist/better-auth/generators/react/better-auth-pages/generated/template-renderers.d.ts +7 -14
- package/dist/better-auth/generators/react/better-auth-pages/generated/typed-templates.d.ts +70 -140
- package/dist/better-auth/generators/react/react-better-auth/generated/index.d.ts +14 -28
- package/dist/better-auth/generators/react/react-better-auth/generated/template-renderers.d.ts +7 -14
- package/dist/better-auth/generators/react/react-better-auth/generated/typed-templates.d.ts +7 -14
- package/dist/better-auth/generators/react/react-better-auth/react-better-auth.generator.d.ts +7 -14
- package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/admin-crud-manage-roles-action.generator.d.ts +14 -28
- package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/generated/index.d.ts +14 -28
- package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/generated/template-renderers.d.ts +7 -14
- package/dist/local-auth/admin/generators/admin-crud-manage-roles-action/generated/typed-templates.d.ts +7 -14
- package/dist/local-auth/admin/generators/admin-crud-reset-password-action/admin-crud-reset-password-action.generator.d.ts +14 -28
- package/dist/local-auth/admin/generators/admin-crud-reset-password-action/generated/index.d.ts +14 -28
- package/dist/local-auth/admin/generators/admin-crud-reset-password-action/generated/template-renderers.d.ts +7 -14
- package/dist/local-auth/admin/generators/admin-crud-reset-password-action/generated/typed-templates.d.ts +14 -28
- package/dist/local-auth/admin/generators/admin-crud-roles-column/admin-crud-roles-column.generator.d.ts +7 -14
- package/dist/local-auth/core/generators/auth-email-password/auth-email-password.generator.d.ts +2 -1
- package/dist/local-auth/core/generators/auth-email-password/generated/index.d.ts +6 -3
- package/dist/local-auth/core/generators/auth-email-password/generated/template-renderers.d.ts +2 -1
- package/dist/local-auth/core/generators/auth-email-password/generated/typed-templates.d.ts +6 -3
- package/dist/local-auth/core/generators/auth-email-password/templates/module/services/email-verification.service.js +2 -2
- package/dist/local-auth/core/generators/auth-email-password/templates/module/services/email-verification.service.ts +2 -2
- package/dist/local-auth/core/generators/auth-email-password/templates/module/services/password-reset.service.js +2 -2
- package/dist/local-auth/core/generators/auth-email-password/templates/module/services/password-reset.service.ts +2 -2
- package/dist/local-auth/core/generators/auth-email-password/templates/module/services/user-password.service.js +8 -5
- package/dist/local-auth/core/generators/auth-email-password/templates/module/services/user-password.service.ts +8 -8
- package/dist/local-auth/core/generators/auth-module/auth-module.generator.d.ts +10 -2
- package/dist/local-auth/core/generators/auth-module/auth-module.generator.js +3 -1
- package/dist/local-auth/core/generators/auth-module/generated/index.d.ts +27 -3
- package/dist/local-auth/core/generators/auth-module/generated/template-renderers.d.ts +9 -1
- package/dist/local-auth/core/generators/auth-module/generated/typed-templates.d.ts +20 -3
- package/dist/local-auth/core/generators/auth-module/templates/module/services/user-session.service.js +18 -16
- package/dist/local-auth/core/generators/auth-module/templates/module/services/user-session.service.ts +18 -16
- package/dist/local-auth/core/generators/auth-module/templates/module/utils/session-cookie.js +6 -6
- package/dist/local-auth/core/generators/auth-module/templates/module/utils/session-cookie.ts +6 -6
- package/dist/local-auth/core/generators/auth-routes/auth-routes.generator.d.ts +7 -14
- package/dist/local-auth/core/generators/auth-routes/generated/index.d.ts +42 -84
- package/dist/local-auth/core/generators/auth-routes/generated/template-renderers.d.ts +7 -14
- package/dist/local-auth/core/generators/auth-routes/generated/typed-templates.d.ts +63 -126
- package/dist/local-auth/core/generators/react-session/generated/index.d.ts +14 -28
- package/dist/local-auth/core/generators/react-session/generated/template-renderers.d.ts +7 -14
- package/dist/local-auth/core/generators/react-session/generated/typed-templates.d.ts +14 -28
- package/dist/local-auth/core/generators/react-session/react-session.generator.d.ts +7 -14
- package/dist/local-auth/core/generators/seed-initial-user/seed-initial-user.generator.js +4 -0
- package/dist/local-auth/core/generators/seed-initial-user/templates/src/prisma/seed-initial-user.js +2 -1
- package/dist/local-auth/core/generators/seed-initial-user/templates/src/prisma/seed-initial-user.ts +3 -1
- package/dist/placeholder-auth/core/generators/placeholder-auth-module/placeholder-auth-module.generator.d.ts +1 -1
- package/dist/placeholder-auth/core/generators/placeholder-auth-module/placeholder-auth-module.generator.js +3 -1
- package/dist/web/assets/{_virtual_mf-localSharedImportMap___mfe_internal__plugin_mf_2_auth-3sV-KVGF.js → _virtual_mf-localSharedImportMap___mfe_internal__plugin_mf_2_auth-04_7KkB1.js} +15 -15
- package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib__loadShare__.js-0m3QgjSy.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib__loadShare__.js-BfSk5vRC.js} +5 -4
- package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib_mf_1_web__loadShare__.js-QrOyqu9V.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_project_mf_2_builder_mf_2_lib_mf_1_web__loadShare__.js-DZIcwf2B.js} +1 -1
- package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-BTSgZGcl.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_baseplate_mf_2_dev_mf_1_ui_mf_2_components__loadShare__.js-CXGct_48.js} +10053 -3750
- package/dist/web/assets/{_virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_tanstack_mf_1_react_mf_2_router__loadShare__.js-CJ027_El.js → _virtual_mf___mfe_internal__plugin_mf_2_auth__loadShare___mf_0_tanstack_mf_1_react_mf_2_router__loadShare__.js-Ci5_qYaj.js} +3823 -2545
- package/dist/web/assets/arduino-BP2nYunF.js +21 -0
- package/dist/web/assets/auth-8qJtXAgU.js +1 -0
- package/dist/web/assets/bash-Zh_IyzBN.js +192 -0
- package/dist/web/assets/basic-3mvohyEL.js +28 -0
- package/dist/web/assets/c-C7Ey31hW.js +74 -0
- package/dist/web/assets/clike-D9YNFwtw.js +41 -0
- package/dist/web/assets/{common-Aq-HXybV.js → common-23-wvKrM.js} +5 -5
- package/dist/web/assets/{common-7-ZtKO5B.js → common-B-NI9TR-.js} +2 -2
- package/dist/web/assets/{common-CDrUdhRf.js → common-BBriDRRy.js} +3 -3
- package/dist/web/assets/{common-BPbNs2A1.js → common-BvU-7KsV.js} +5 -5
- package/dist/web/assets/{common-B_XZ3l9w.js → common-DBBUvtGu.js} +2 -2
- package/dist/web/assets/{common-B8N9gx2s.js → common-eFh2vwGb.js} +3 -3
- package/dist/web/assets/cpp-_RjA_yNA.js +82 -0
- package/dist/web/assets/csharp-0LZzOc6Q.js +301 -0
- package/dist/web/assets/css-D7TbgetL.js +70 -0
- package/dist/web/assets/diff-CtSa_15w.js +54 -0
- package/dist/web/assets/{dist-D3CkiDKT.js → dist-BjxypexQ.js} +1672 -992
- package/dist/web/assets/{get-auth-plugin-definition-D3ocnNxw.js → get-auth-plugin-definition-x8oAsN1R.js} +2 -2
- package/dist/web/assets/go-CzER04EZ.js +36 -0
- package/dist/web/assets/{hostInit-D3RxwboF.js → hostInit-Bay0Y9UX.js} +1 -1
- package/dist/web/assets/{index-CozZxQl1.js → index-qso1IsKy.js} +2 -2
- package/dist/web/assets/ini-CU-wHLTy.js +51 -0
- package/dist/web/assets/java-HAvRESj1.js +116 -0
- package/dist/web/assets/javascript-BVAr0eZH.js +124 -0
- package/dist/web/assets/json-DN8T4yFI.js +38 -0
- package/dist/web/assets/kotlin-DkCMjTKK.js +83 -0
- package/dist/web/assets/less-ZXX1tgaG.js +42 -0
- package/dist/web/assets/lua-D9bD4wrb.js +28 -0
- package/dist/web/assets/makefile-CKoRpler.js +40 -0
- package/dist/web/assets/markdown-_2_uVr2L.js +278 -0
- package/dist/web/assets/markup-BVZ8HhdW.js +176 -0
- package/dist/web/assets/markup-templating-BDIRuVJH.js +94 -0
- package/dist/web/assets/{mf-entry-bootstrap-0-069a3ab2.js → mf-entry-bootstrap-0-659c976f.js} +2 -2
- package/dist/web/assets/{model-utils-CYaLYwoX.js → model-utils-dNFTOjqi.js} +305 -27
- package/dist/web/assets/{models-BX4xFiEn.js → models-BpslIbU7.js} +2 -2
- package/dist/web/assets/{models-k-iaCft-.js → models-CKab4MTC.js} +2 -2
- package/dist/web/assets/objectivec-DPgB68It.js +25 -0
- package/dist/web/assets/perl-Cul_ma_h.js +92 -0
- package/dist/web/assets/php-JTON0zp9.js +298 -0
- package/dist/web/assets/{plugin-definition-CI1aEVGv.js → plugin-definition-8Exesd6T.js} +2 -2
- package/dist/web/assets/{plugin-definition-BI565qFo.js → plugin-definition-ChBrbazJ.js} +2 -2
- package/dist/web/assets/python-CURlmZ7M.js +73 -0
- package/dist/web/assets/r-8lr7pbGm.js +30 -0
- package/dist/web/assets/regex-CxQ7DXCx.js +96 -0
- package/dist/web/assets/ruby-BoFHz67P.js +175 -0
- package/dist/web/assets/rust-CpZXpaj0.js +107 -0
- package/dist/web/assets/sass-DG0YAnL7.js +65 -0
- package/dist/web/assets/scss-BDRIqhak.js +70 -0
- package/dist/web/assets/sql-C-bL8_gT.js +40 -0
- package/dist/web/assets/{styles-f4jHVv0S.js → styles-Cuq4wgvD.js} +7 -7
- package/dist/web/assets/swift-rQ52kfab.js +107 -0
- package/dist/web/assets/typescript-CDkIWcT8.js +57 -0
- package/dist/web/assets/vbnet-_PL7-T9d.js +32 -0
- package/dist/web/assets/{virtualExposes-BHQhgLE-.js → virtualExposes-BwIds34r.js} +1 -1
- package/dist/web/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__plugin-auth__remoteEntry_js-aH8n-Nbe.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__plugin-auth__remoteEntry_js-BBt5f0I7.js} +3 -3
- package/dist/web/assets/{virtual_mf-exposes-ssr___mfe_internal__plugin-auth__remoteEntry_js-I_SxfvGj.js → virtual_mf-exposes-ssr___mfe_internal__plugin-auth__remoteEntry_js-RzPgl37a.js} +13 -13
- package/dist/web/assets/{virtual_mf-exposes___mfe_internal__plugin-auth__remoteEntry_js-BQ0UMKSv.js → virtual_mf-exposes___mfe_internal__plugin-auth__remoteEntry_js-DM6Ir1_S.js} +13 -13
- package/dist/web/assets/{web-DCK_tLVa.js → web-BZd3bM0n.js} +6 -6
- package/dist/web/assets/{web-CkbTu31Q.js → web-BgWG7dYl.js} +10 -10
- package/dist/web/assets/{web-Dh6pUTrF.js → web-CXHw8SK7.js} +13 -13
- package/dist/web/assets/{web-Cn3uvuFs.js → web-CnB-sqCR.js} +20 -18
- package/dist/web/assets/{web-BRvS0HRS.js → web-DHv2aVpi.js} +10 -10
- package/dist/web/assets/{web-YXVJWeXy.js → web-DNrWXjpS.js} +3 -3
- package/dist/web/assets/{web-nLSlkJy_.js → web-D_H-MoGI.js} +3 -3
- package/dist/web/assets/workerBundle-GFUata9j.js +10 -0
- package/dist/web/assets/yaml-C9m3vuV5.js +90 -0
- package/dist/web/index.html +2 -2
- package/dist/web/remoteEntry.js +1 -1
- package/dist/web/remoteEntry.ssr.js +1 -1
- package/package.json +18 -17
- package/dist/web/assets/auth-D8BnFQKk.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import { EMAIL_VERIFICATION_TOKEN_EXPIRY_SEC } from '$constantsPassword';
|
|
3
3
|
import { createAuthVerification, validateAuthVerification, } from '%authModuleImports';
|
|
4
|
-
import {
|
|
4
|
+
import { getConfig } from '%configServiceImports';
|
|
5
5
|
import { BadRequestError } from '%errorHandlerServiceImports';
|
|
6
6
|
import { prisma } from '%prismaImports';
|
|
7
7
|
import { memoizeRateLimiter } from '%rateLimitImports';
|
|
@@ -50,7 +50,7 @@ export async function requestEmailVerification({ userId, context, }) {
|
|
|
50
50
|
expiresInSec: EMAIL_VERIFICATION_TOKEN_EXPIRY_SEC,
|
|
51
51
|
});
|
|
52
52
|
// Construct verification URL using configured domain
|
|
53
|
-
const verifyLink = `${
|
|
53
|
+
const verifyLink = `${getConfig().AUTH_FRONTEND_URL}/auth/verify-email?token=${encodeURIComponent(token)}`;
|
|
54
54
|
await services.email.send(TPL_ACCOUNT_VERIFICATION_EMAIL, {
|
|
55
55
|
to: user.email,
|
|
56
56
|
data: { verifyLink },
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
createAuthVerification,
|
|
11
11
|
validateAuthVerification,
|
|
12
12
|
} from '%authModuleImports';
|
|
13
|
-
import {
|
|
13
|
+
import { getConfig } from '%configServiceImports';
|
|
14
14
|
import { BadRequestError } from '%errorHandlerServiceImports';
|
|
15
15
|
import { prisma } from '%prismaImports';
|
|
16
16
|
import { memoizeRateLimiter } from '%rateLimitImports';
|
|
@@ -91,7 +91,7 @@ export async function requestEmailVerification({
|
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
// Construct verification URL using configured domain
|
|
94
|
-
const verifyLink = `${
|
|
94
|
+
const verifyLink = `${getConfig().AUTH_FRONTEND_URL}/auth/verify-email?token=${encodeURIComponent(token)}`;
|
|
95
95
|
|
|
96
96
|
await services.email.send(TPL_ACCOUNT_VERIFICATION_EMAIL, {
|
|
97
97
|
to: user.email,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, PASSWORD_RESET_TOKEN_EXPIRY_SEC, } from '$constantsPassword';
|
|
3
3
|
import { resetLoginRateLimits } from '$servicesUserPassword';
|
|
4
4
|
import { createAuthVerification, validateAuthVerification, } from '%authModuleImports';
|
|
5
|
-
import {
|
|
5
|
+
import { getConfig } from '%configServiceImports';
|
|
6
6
|
import { BadRequestError, handleZodRequestValidationError, } from '%errorHandlerServiceImports';
|
|
7
7
|
import { createPasswordHash } from '%passwordHasherServiceImports';
|
|
8
8
|
import { prisma } from '%prismaImports';
|
|
@@ -59,7 +59,7 @@ export async function requestPasswordReset({ email: rawEmail, context, }) {
|
|
|
59
59
|
expiresInSec: PASSWORD_RESET_TOKEN_EXPIRY_SEC,
|
|
60
60
|
});
|
|
61
61
|
// Construct reset URL using configured domain
|
|
62
|
-
const resetLink = `${
|
|
62
|
+
const resetLink = `${getConfig().AUTH_FRONTEND_URL}/auth/reset-password?token=${encodeURIComponent(token)}`;
|
|
63
63
|
// Send email asynchronously (queue-based)
|
|
64
64
|
await services.email.send(TPL_PASSWORD_RESET_EMAIL, {
|
|
65
65
|
to: user.email,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
createAuthVerification,
|
|
13
13
|
validateAuthVerification,
|
|
14
14
|
} from '%authModuleImports';
|
|
15
|
-
import {
|
|
15
|
+
import { getConfig } from '%configServiceImports';
|
|
16
16
|
import {
|
|
17
17
|
BadRequestError,
|
|
18
18
|
handleZodRequestValidationError,
|
|
@@ -108,7 +108,7 @@ export async function requestPasswordReset({
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
// Construct reset URL using configured domain
|
|
111
|
-
const resetLink = `${
|
|
111
|
+
const resetLink = `${getConfig().AUTH_FRONTEND_URL}/auth/reset-password?token=${encodeURIComponent(token)}`;
|
|
112
112
|
|
|
113
113
|
// Send email asynchronously (queue-based)
|
|
114
114
|
await services.email.send(TPL_PASSWORD_RESET_EMAIL, {
|
|
@@ -94,8 +94,8 @@ export async function authenticateUserWithEmailAndPassword({ input, context, })
|
|
|
94
94
|
const clientIp = context.reqInfo.ip;
|
|
95
95
|
const emailIpKey = `${email}_${clientIp}`;
|
|
96
96
|
// Check IP-based rate limit (slow brute force protection)
|
|
97
|
-
const ipResult = await getLoginIpLimiter().
|
|
98
|
-
if (!ipResult.allowed) {
|
|
97
|
+
const ipResult = await getLoginIpLimiter().get(clientIp);
|
|
98
|
+
if (ipResult && !ipResult.allowed) {
|
|
99
99
|
throw new TooManyRequestsError('Too many login attempts. Please try again later or reset your password.', 'login-ip-rate-limited', { retryAfterMs: ipResult.msBeforeNext });
|
|
100
100
|
}
|
|
101
101
|
// Check consecutive failures rate limit (fast brute force protection)
|
|
@@ -113,10 +113,13 @@ export async function authenticateUserWithEmailAndPassword({ input, context, })
|
|
|
113
113
|
},
|
|
114
114
|
});
|
|
115
115
|
// check for password match
|
|
116
|
-
const isValid = await verifyPasswordHash(userAccount?.password
|
|
116
|
+
const isValid = await verifyPasswordHash(userAccount?.password, password);
|
|
117
117
|
if (!isValid || !userAccount) {
|
|
118
118
|
// Track failed attempt
|
|
119
|
-
await
|
|
119
|
+
await Promise.all([
|
|
120
|
+
getLoginIpLimiter().consume(clientIp),
|
|
121
|
+
getLoginConsecutiveFailsLimiter().consume(emailIpKey),
|
|
122
|
+
]);
|
|
120
123
|
throw new BadRequestError('Invalid email or password', 'invalid-credentials');
|
|
121
124
|
}
|
|
122
125
|
// Reset consecutive failures on successful login
|
|
@@ -149,7 +152,7 @@ export async function changeUserPassword({ userId, input, }) {
|
|
|
149
152
|
},
|
|
150
153
|
});
|
|
151
154
|
// Verify current password
|
|
152
|
-
const isValid = await verifyPasswordHash(userAccount?.password
|
|
155
|
+
const isValid = await verifyPasswordHash(userAccount?.password, currentPassword);
|
|
153
156
|
if (!isValid || !userAccount) {
|
|
154
157
|
throw new BadRequestError('Current password is incorrect', 'invalid-current-password');
|
|
155
158
|
}
|
|
@@ -169,8 +169,8 @@ export async function authenticateUserWithEmailAndPassword({
|
|
|
169
169
|
const emailIpKey = `${email}_${clientIp}`;
|
|
170
170
|
|
|
171
171
|
// Check IP-based rate limit (slow brute force protection)
|
|
172
|
-
const ipResult = await getLoginIpLimiter().
|
|
173
|
-
if (!ipResult.allowed) {
|
|
172
|
+
const ipResult = await getLoginIpLimiter().get(clientIp);
|
|
173
|
+
if (ipResult && !ipResult.allowed) {
|
|
174
174
|
throw new TooManyRequestsError(
|
|
175
175
|
'Too many login attempts. Please try again later or reset your password.',
|
|
176
176
|
'login-ip-rate-limited',
|
|
@@ -201,13 +201,13 @@ export async function authenticateUserWithEmailAndPassword({
|
|
|
201
201
|
});
|
|
202
202
|
|
|
203
203
|
// check for password match
|
|
204
|
-
const isValid = await verifyPasswordHash(
|
|
205
|
-
userAccount?.password ?? '',
|
|
206
|
-
password,
|
|
207
|
-
);
|
|
204
|
+
const isValid = await verifyPasswordHash(userAccount?.password, password);
|
|
208
205
|
if (!isValid || !userAccount) {
|
|
209
206
|
// Track failed attempt
|
|
210
|
-
await
|
|
207
|
+
await Promise.all([
|
|
208
|
+
getLoginIpLimiter().consume(clientIp),
|
|
209
|
+
getLoginConsecutiveFailsLimiter().consume(emailIpKey),
|
|
210
|
+
]);
|
|
211
211
|
throw new BadRequestError(
|
|
212
212
|
'Invalid email or password',
|
|
213
213
|
'invalid-credentials',
|
|
@@ -263,7 +263,7 @@ export async function changeUserPassword({
|
|
|
263
263
|
|
|
264
264
|
// Verify current password
|
|
265
265
|
const isValid = await verifyPasswordHash(
|
|
266
|
-
userAccount?.password
|
|
266
|
+
userAccount?.password,
|
|
267
267
|
currentPassword,
|
|
268
268
|
);
|
|
269
269
|
if (!isValid || !userAccount) {
|
|
@@ -50,7 +50,8 @@ export declare const authModuleGenerator: import("@baseplate-dev/sync").Generato
|
|
|
50
50
|
};
|
|
51
51
|
}>>;
|
|
52
52
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
53
|
-
|
|
53
|
+
getConfig: {};
|
|
54
|
+
isDevelopment: {};
|
|
54
55
|
}>>;
|
|
55
56
|
errorHandlerServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
56
57
|
BadRequestError: {};
|
|
@@ -79,6 +80,7 @@ export declare const authModuleGenerator: import("@baseplate-dev/sync").Generato
|
|
|
79
80
|
}>>;
|
|
80
81
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
81
82
|
bindQueueHandler: {};
|
|
83
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
82
84
|
defineQueue: {};
|
|
83
85
|
EnqueueOptions: {
|
|
84
86
|
isTypeOnly: true;
|
|
@@ -104,6 +106,12 @@ export declare const authModuleGenerator: import("@baseplate-dev/sync").Generato
|
|
|
104
106
|
QueueJobHandler: {
|
|
105
107
|
isTypeOnly: true;
|
|
106
108
|
};
|
|
109
|
+
QueuePolicyFixPlan: {
|
|
110
|
+
isTypeOnly: true;
|
|
111
|
+
};
|
|
112
|
+
QueuePolicyFixResult: {
|
|
113
|
+
isTypeOnly: true;
|
|
114
|
+
};
|
|
107
115
|
QueueRuntime: {
|
|
108
116
|
isTypeOnly: true;
|
|
109
117
|
};
|
|
@@ -160,7 +168,7 @@ export declare const authModuleGenerator: import("@baseplate-dev/sync").Generato
|
|
|
160
168
|
}, any>;
|
|
161
169
|
appRuntimeConfig: import("@baseplate-dev/sync").GeneratorTask<any, {
|
|
162
170
|
appRuntimeConfig: import("@baseplate-dev/sync").ProviderType<Omit<import("@baseplate-dev/utils").FieldMap<{
|
|
163
|
-
services: import("@baseplate-dev/utils").MapContainer<string, import("@baseplate-dev/
|
|
171
|
+
services: import("@baseplate-dev/utils").MapContainer<string, import("@baseplate-dev/fastify-generators").AppRuntimeServiceEntry>;
|
|
164
172
|
construction: import("@baseplate-dev/utils").MapContainer<string, import("@baseplate-dev/fastify-generators").AppRuntimeConstructionEntry>;
|
|
165
173
|
flattenedModuleFields: import("@baseplate-dev/utils").MapContainer<string, string>;
|
|
166
174
|
usesBackgroundServices: import("@baseplate-dev/utils").ScalarContainer<boolean | undefined>;
|
|
@@ -102,7 +102,9 @@ export const authModuleGenerator = createGenerator({
|
|
|
102
102
|
paths: GENERATED_TEMPLATES.paths.provider,
|
|
103
103
|
},
|
|
104
104
|
run({ appRuntimeConfig, paths }) {
|
|
105
|
-
appRuntimeConfig.services.set('userSession',
|
|
105
|
+
appRuntimeConfig.services.set('userSession', {
|
|
106
|
+
type: tsCodeFragment('CookieUserSessionService', tsTypeImportBuilder(['CookieUserSessionService']).from(paths.userSessionService)),
|
|
107
|
+
});
|
|
106
108
|
appRuntimeConfig.construction.set('userSession', {
|
|
107
109
|
fragment: TsCodeUtils.template `new ${TsCodeUtils.importFragment('CookieUserSessionService', paths.userSessionService)}()`,
|
|
108
110
|
});
|
|
@@ -54,7 +54,8 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
54
54
|
};
|
|
55
55
|
}>>;
|
|
56
56
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
57
|
-
|
|
57
|
+
getConfig: {};
|
|
58
|
+
isDevelopment: {};
|
|
58
59
|
}>>;
|
|
59
60
|
errorHandlerServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
60
61
|
BadRequestError: {};
|
|
@@ -83,6 +84,7 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
83
84
|
}>>;
|
|
84
85
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
85
86
|
bindQueueHandler: {};
|
|
87
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
86
88
|
defineQueue: {};
|
|
87
89
|
EnqueueOptions: {
|
|
88
90
|
isTypeOnly: true;
|
|
@@ -108,6 +110,12 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
108
110
|
QueueJobHandler: {
|
|
109
111
|
isTypeOnly: true;
|
|
110
112
|
};
|
|
113
|
+
QueuePolicyFixPlan: {
|
|
114
|
+
isTypeOnly: true;
|
|
115
|
+
};
|
|
116
|
+
QueuePolicyFixResult: {
|
|
117
|
+
isTypeOnly: true;
|
|
118
|
+
};
|
|
111
119
|
QueueRuntime: {
|
|
112
120
|
isTypeOnly: true;
|
|
113
121
|
};
|
|
@@ -243,6 +251,7 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
243
251
|
queuesCleanupAuthVerification: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
244
252
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
245
253
|
bindQueueHandler: {};
|
|
254
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
246
255
|
defineQueue: {};
|
|
247
256
|
EnqueueOptions: {
|
|
248
257
|
isTypeOnly: true;
|
|
@@ -268,6 +277,12 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
268
277
|
QueueJobHandler: {
|
|
269
278
|
isTypeOnly: true;
|
|
270
279
|
};
|
|
280
|
+
QueuePolicyFixPlan: {
|
|
281
|
+
isTypeOnly: true;
|
|
282
|
+
};
|
|
283
|
+
QueuePolicyFixResult: {
|
|
284
|
+
isTypeOnly: true;
|
|
285
|
+
};
|
|
271
286
|
QueueRuntime: {
|
|
272
287
|
isTypeOnly: true;
|
|
273
288
|
};
|
|
@@ -291,6 +306,7 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
291
306
|
queuesCleanupAuthVerificationWorker: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
292
307
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
293
308
|
bindQueueHandler: {};
|
|
309
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
294
310
|
defineQueue: {};
|
|
295
311
|
EnqueueOptions: {
|
|
296
312
|
isTypeOnly: true;
|
|
@@ -316,6 +332,12 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
316
332
|
QueueJobHandler: {
|
|
317
333
|
isTypeOnly: true;
|
|
318
334
|
};
|
|
335
|
+
QueuePolicyFixPlan: {
|
|
336
|
+
isTypeOnly: true;
|
|
337
|
+
};
|
|
338
|
+
QueuePolicyFixResult: {
|
|
339
|
+
isTypeOnly: true;
|
|
340
|
+
};
|
|
319
341
|
QueueRuntime: {
|
|
320
342
|
isTypeOnly: true;
|
|
321
343
|
};
|
|
@@ -380,7 +402,8 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
380
402
|
};
|
|
381
403
|
}>>;
|
|
382
404
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
383
|
-
|
|
405
|
+
getConfig: {};
|
|
406
|
+
isDevelopment: {};
|
|
384
407
|
}>>;
|
|
385
408
|
errorHandlerServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
386
409
|
BadRequestError: {};
|
|
@@ -424,7 +447,8 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_GENERATED: {
|
|
|
424
447
|
cookieSigner: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {}, Record<never, Record<never, never>>>;
|
|
425
448
|
sessionCookie: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
426
449
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
427
|
-
|
|
450
|
+
getConfig: {};
|
|
451
|
+
isDevelopment: {};
|
|
428
452
|
}>>;
|
|
429
453
|
}, Record<never, Record<never, never>>>;
|
|
430
454
|
verifyRequestOrigin: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {}, Record<never, Record<never, never>>>;
|
|
@@ -56,7 +56,8 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_RENDERERS: {
|
|
|
56
56
|
};
|
|
57
57
|
}>>;
|
|
58
58
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
59
|
-
|
|
59
|
+
getConfig: {};
|
|
60
|
+
isDevelopment: {};
|
|
60
61
|
}>>;
|
|
61
62
|
errorHandlerServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
62
63
|
BadRequestError: {};
|
|
@@ -85,6 +86,7 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_RENDERERS: {
|
|
|
85
86
|
}>>;
|
|
86
87
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
87
88
|
bindQueueHandler: {};
|
|
89
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
88
90
|
defineQueue: {};
|
|
89
91
|
EnqueueOptions: {
|
|
90
92
|
isTypeOnly: true;
|
|
@@ -110,6 +112,12 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_RENDERERS: {
|
|
|
110
112
|
QueueJobHandler: {
|
|
111
113
|
isTypeOnly: true;
|
|
112
114
|
};
|
|
115
|
+
QueuePolicyFixPlan: {
|
|
116
|
+
isTypeOnly: true;
|
|
117
|
+
};
|
|
118
|
+
QueuePolicyFixResult: {
|
|
119
|
+
isTypeOnly: true;
|
|
120
|
+
};
|
|
113
121
|
QueueRuntime: {
|
|
114
122
|
isTypeOnly: true;
|
|
115
123
|
};
|
|
@@ -94,7 +94,8 @@ export declare const utilsGroup: {
|
|
|
94
94
|
cookieSigner: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {}, Record<never, Record<never, never>>>;
|
|
95
95
|
sessionCookie: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
96
96
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
97
|
-
|
|
97
|
+
getConfig: {};
|
|
98
|
+
isDevelopment: {};
|
|
98
99
|
}>>;
|
|
99
100
|
}, Record<never, Record<never, never>>>;
|
|
100
101
|
verifyRequestOrigin: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {}, Record<never, Record<never, never>>>;
|
|
@@ -195,6 +196,7 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_TEMPLATES: {
|
|
|
195
196
|
queuesCleanupAuthVerification: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
196
197
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
197
198
|
bindQueueHandler: {};
|
|
199
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
198
200
|
defineQueue: {};
|
|
199
201
|
EnqueueOptions: {
|
|
200
202
|
isTypeOnly: true;
|
|
@@ -220,6 +222,12 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_TEMPLATES: {
|
|
|
220
222
|
QueueJobHandler: {
|
|
221
223
|
isTypeOnly: true;
|
|
222
224
|
};
|
|
225
|
+
QueuePolicyFixPlan: {
|
|
226
|
+
isTypeOnly: true;
|
|
227
|
+
};
|
|
228
|
+
QueuePolicyFixResult: {
|
|
229
|
+
isTypeOnly: true;
|
|
230
|
+
};
|
|
223
231
|
QueueRuntime: {
|
|
224
232
|
isTypeOnly: true;
|
|
225
233
|
};
|
|
@@ -243,6 +251,7 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_TEMPLATES: {
|
|
|
243
251
|
queuesCleanupAuthVerificationWorker: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
244
252
|
queuesImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
245
253
|
bindQueueHandler: {};
|
|
254
|
+
DEFAULT_QUEUE_CONCURRENCY: {};
|
|
246
255
|
defineQueue: {};
|
|
247
256
|
EnqueueOptions: {
|
|
248
257
|
isTypeOnly: true;
|
|
@@ -268,6 +277,12 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_TEMPLATES: {
|
|
|
268
277
|
QueueJobHandler: {
|
|
269
278
|
isTypeOnly: true;
|
|
270
279
|
};
|
|
280
|
+
QueuePolicyFixPlan: {
|
|
281
|
+
isTypeOnly: true;
|
|
282
|
+
};
|
|
283
|
+
QueuePolicyFixResult: {
|
|
284
|
+
isTypeOnly: true;
|
|
285
|
+
};
|
|
271
286
|
QueueRuntime: {
|
|
272
287
|
isTypeOnly: true;
|
|
273
288
|
};
|
|
@@ -332,7 +347,8 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_TEMPLATES: {
|
|
|
332
347
|
};
|
|
333
348
|
}>>;
|
|
334
349
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
335
|
-
|
|
350
|
+
getConfig: {};
|
|
351
|
+
isDevelopment: {};
|
|
336
352
|
}>>;
|
|
337
353
|
errorHandlerServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
338
354
|
BadRequestError: {};
|
|
@@ -376,7 +392,8 @@ export declare const LOCAL_AUTH_CORE_AUTH_MODULE_TEMPLATES: {
|
|
|
376
392
|
cookieSigner: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {}, Record<never, Record<never, never>>>;
|
|
377
393
|
sessionCookie: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {
|
|
378
394
|
configServiceImports: import("@baseplate-dev/sync").ProviderType<import("@baseplate-dev/core-generators").InferTsImportMapFromSchema<{
|
|
379
|
-
|
|
395
|
+
getConfig: {};
|
|
396
|
+
isDevelopment: {};
|
|
380
397
|
}>>;
|
|
381
398
|
}, Record<never, Record<never, never>>>;
|
|
382
399
|
verifyRequestOrigin: import("@baseplate-dev/core-generators").TsTemplateFile<{}, {}, Record<never, Record<never, never>>>;
|
|
@@ -5,17 +5,19 @@ import { USER_SESSION_DURATION_SEC, USER_SESSION_MAX_LIFETIME_SEC, USER_SESSION_
|
|
|
5
5
|
import { verifyRequestOrigin } from '$verifyRequestOrigin';
|
|
6
6
|
import { InvalidSessionError } from '%authContextImports';
|
|
7
7
|
import { DEFAULT_USER_ROLES } from '%authRolesImports';
|
|
8
|
-
import {
|
|
8
|
+
import { getConfig, isDevelopment } from '%configServiceImports';
|
|
9
9
|
import { ForbiddenError } from '%errorHandlerServiceImports';
|
|
10
10
|
import { prisma } from '%prismaImports';
|
|
11
11
|
import { randomBytes } from 'node:crypto';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
function getCookieOptions() {
|
|
13
|
+
return {
|
|
14
|
+
httpOnly: true,
|
|
15
|
+
sameSite: 'lax',
|
|
16
|
+
secure: !isDevelopment(),
|
|
17
|
+
maxAge: USER_SESSION_DURATION_SEC,
|
|
18
|
+
path: '/',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
19
21
|
/**
|
|
20
22
|
* Validates the expiry of a user session and determines if it needs to be renewed.
|
|
21
23
|
*
|
|
@@ -83,8 +85,8 @@ export class CookieUserSessionService {
|
|
|
83
85
|
...user.roles.map((role) => role.role),
|
|
84
86
|
];
|
|
85
87
|
const cookieName = getUserSessionCookieName(context.reqInfo.headers);
|
|
86
|
-
const cookieValue = signObject({ token },
|
|
87
|
-
context.cookieStore.set(cookieName, cookieValue,
|
|
88
|
+
const cookieValue = signObject({ token }, getConfig().AUTH_SECRET);
|
|
89
|
+
context.cookieStore.set(cookieName, cookieValue, getCookieOptions());
|
|
88
90
|
return { userId, expiresAt, roles };
|
|
89
91
|
}
|
|
90
92
|
/**
|
|
@@ -98,7 +100,7 @@ export class CookieUserSessionService {
|
|
|
98
100
|
where: { id: sessionInfo.id },
|
|
99
101
|
});
|
|
100
102
|
const cookieName = getUserSessionCookieName(context.reqInfo.headers);
|
|
101
|
-
context.cookieStore.clear(cookieName,
|
|
103
|
+
context.cookieStore.clear(cookieName, getCookieOptions());
|
|
102
104
|
}
|
|
103
105
|
/**
|
|
104
106
|
* Retrieves the user session information from the request.
|
|
@@ -120,12 +122,12 @@ export class CookieUserSessionService {
|
|
|
120
122
|
if ((req.method !== 'GET' ||
|
|
121
123
|
req.headers.upgrade?.toLowerCase() === 'websocket') &&
|
|
122
124
|
req.method !== 'HEAD' &&
|
|
123
|
-
!verifyRequestOrigin(req, [req.host, ...
|
|
125
|
+
!verifyRequestOrigin(req, [req.host, ...getConfig().ALLOWED_ORIGINS])) {
|
|
124
126
|
throw new ForbiddenError('Invalid Origin header');
|
|
125
127
|
}
|
|
126
128
|
try {
|
|
127
129
|
// Unsign the session cookie
|
|
128
|
-
const sessionCookieResult = unsignObject(sessionCookieValue,
|
|
130
|
+
const sessionCookieResult = unsignObject(sessionCookieValue, getConfig().AUTH_SECRET);
|
|
129
131
|
if (!sessionCookieResult)
|
|
130
132
|
throw new InvalidSessionError();
|
|
131
133
|
const { token } = sessionCookieResult;
|
|
@@ -150,8 +152,8 @@ export class CookieUserSessionService {
|
|
|
150
152
|
expiresAt: sessionExpiryResult.newExpiry,
|
|
151
153
|
},
|
|
152
154
|
});
|
|
153
|
-
const newSignedCookie = signObject({ token },
|
|
154
|
-
reply.setCookie(cookieName, newSignedCookie,
|
|
155
|
+
const newSignedCookie = signObject({ token }, getConfig().AUTH_SECRET);
|
|
156
|
+
reply.setCookie(cookieName, newSignedCookie, getCookieOptions());
|
|
155
157
|
}
|
|
156
158
|
const { user } = userSession;
|
|
157
159
|
const expiresAt = sessionExpiryResult.newExpiry ?? userSession.expiresAt;
|
|
@@ -169,7 +171,7 @@ export class CookieUserSessionService {
|
|
|
169
171
|
catch (err) {
|
|
170
172
|
// clear the cookie if it's invalid
|
|
171
173
|
if (err instanceof InvalidSessionError && reply) {
|
|
172
|
-
reply.clearCookie(cookieName,
|
|
174
|
+
reply.clearCookie(cookieName, getCookieOptions());
|
|
173
175
|
}
|
|
174
176
|
throw err;
|
|
175
177
|
}
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import { verifyRequestOrigin } from '$verifyRequestOrigin';
|
|
21
21
|
import { InvalidSessionError } from '%authContextImports';
|
|
22
22
|
import { DEFAULT_USER_ROLES } from '%authRolesImports';
|
|
23
|
-
import {
|
|
23
|
+
import { getConfig, isDevelopment } from '%configServiceImports';
|
|
24
24
|
import { ForbiddenError } from '%errorHandlerServiceImports';
|
|
25
25
|
import { prisma } from '%prismaImports';
|
|
26
26
|
import { randomBytes } from 'node:crypto';
|
|
@@ -30,13 +30,15 @@ interface SessionCookieValue {
|
|
|
30
30
|
token: string;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
function getCookieOptions(): CookieSerializeOptions {
|
|
34
|
+
return {
|
|
35
|
+
httpOnly: true,
|
|
36
|
+
sameSite: 'lax',
|
|
37
|
+
secure: !isDevelopment(),
|
|
38
|
+
maxAge: USER_SESSION_DURATION_SEC,
|
|
39
|
+
path: '/',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
40
42
|
|
|
41
43
|
/**
|
|
42
44
|
* Validates the expiry of a user session and determines if it needs to be renewed.
|
|
@@ -129,9 +131,9 @@ export class CookieUserSessionService implements UserSessionService {
|
|
|
129
131
|
];
|
|
130
132
|
|
|
131
133
|
const cookieName = getUserSessionCookieName(context.reqInfo.headers);
|
|
132
|
-
const cookieValue = signObject({ token },
|
|
134
|
+
const cookieValue = signObject({ token }, getConfig().AUTH_SECRET);
|
|
133
135
|
|
|
134
|
-
context.cookieStore.set(cookieName, cookieValue,
|
|
136
|
+
context.cookieStore.set(cookieName, cookieValue, getCookieOptions());
|
|
135
137
|
|
|
136
138
|
return { userId, expiresAt, roles };
|
|
137
139
|
}
|
|
@@ -151,7 +153,7 @@ export class CookieUserSessionService implements UserSessionService {
|
|
|
151
153
|
});
|
|
152
154
|
|
|
153
155
|
const cookieName = getUserSessionCookieName(context.reqInfo.headers);
|
|
154
|
-
context.cookieStore.clear(cookieName,
|
|
156
|
+
context.cookieStore.clear(cookieName, getCookieOptions());
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
/**
|
|
@@ -180,7 +182,7 @@ export class CookieUserSessionService implements UserSessionService {
|
|
|
180
182
|
(req.method !== 'GET' ||
|
|
181
183
|
req.headers.upgrade?.toLowerCase() === 'websocket') &&
|
|
182
184
|
req.method !== 'HEAD' &&
|
|
183
|
-
!verifyRequestOrigin(req, [req.host, ...
|
|
185
|
+
!verifyRequestOrigin(req, [req.host, ...getConfig().ALLOWED_ORIGINS])
|
|
184
186
|
) {
|
|
185
187
|
throw new ForbiddenError('Invalid Origin header');
|
|
186
188
|
}
|
|
@@ -188,7 +190,7 @@ export class CookieUserSessionService implements UserSessionService {
|
|
|
188
190
|
// Unsign the session cookie
|
|
189
191
|
const sessionCookieResult = unsignObject(
|
|
190
192
|
sessionCookieValue,
|
|
191
|
-
|
|
193
|
+
getConfig().AUTH_SECRET,
|
|
192
194
|
) as SessionCookieValue | undefined;
|
|
193
195
|
if (!sessionCookieResult) throw new InvalidSessionError();
|
|
194
196
|
|
|
@@ -218,8 +220,8 @@ export class CookieUserSessionService implements UserSessionService {
|
|
|
218
220
|
expiresAt: sessionExpiryResult.newExpiry,
|
|
219
221
|
},
|
|
220
222
|
});
|
|
221
|
-
const newSignedCookie = signObject({ token },
|
|
222
|
-
reply.setCookie(cookieName, newSignedCookie,
|
|
223
|
+
const newSignedCookie = signObject({ token }, getConfig().AUTH_SECRET);
|
|
224
|
+
reply.setCookie(cookieName, newSignedCookie, getCookieOptions());
|
|
223
225
|
}
|
|
224
226
|
|
|
225
227
|
const { user } = userSession;
|
|
@@ -238,7 +240,7 @@ export class CookieUserSessionService implements UserSessionService {
|
|
|
238
240
|
} catch (err) {
|
|
239
241
|
// clear the cookie if it's invalid
|
|
240
242
|
if (err instanceof InvalidSessionError && reply) {
|
|
241
|
-
reply.clearCookie(cookieName,
|
|
243
|
+
reply.clearCookie(cookieName, getCookieOptions());
|
|
242
244
|
}
|
|
243
245
|
throw err;
|
|
244
246
|
}
|
package/dist/local-auth/core/generators/auth-module/templates/module/utils/session-cookie.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import {
|
|
2
|
+
import { getConfig, isDevelopment } from '%configServiceImports';
|
|
3
3
|
const COOKIE_NAME = 'user-session';
|
|
4
4
|
/**
|
|
5
5
|
* Retrieves the name of the session cookie based on the provided request.
|
|
@@ -10,9 +10,10 @@ const COOKIE_NAME = 'user-session';
|
|
|
10
10
|
* @returns The name of the Iron session cookie.
|
|
11
11
|
*/
|
|
12
12
|
export function getUserSessionCookieName(headers) {
|
|
13
|
-
if (
|
|
13
|
+
if (!isDevelopment()) {
|
|
14
14
|
return `__Host-${COOKIE_NAME}`;
|
|
15
15
|
}
|
|
16
|
+
const { SERVER_PORT } = getConfig();
|
|
16
17
|
// in development, localhost does not support the __Host prefix and should be scoped to port
|
|
17
18
|
// use origin/referer header to determine hostname because dev reverse proxies use origin/referer to signal the original host
|
|
18
19
|
const { origin, referer } = headers;
|
|
@@ -20,18 +21,17 @@ export function getUserSessionCookieName(headers) {
|
|
|
20
21
|
let port;
|
|
21
22
|
try {
|
|
22
23
|
if (!originalHost) {
|
|
23
|
-
port =
|
|
24
|
+
port = SERVER_PORT;
|
|
24
25
|
}
|
|
25
26
|
else {
|
|
26
27
|
const url = new URL(originalHost);
|
|
27
28
|
const parsedPort = Number.parseInt(url.port, 10);
|
|
28
29
|
// Validate port is in valid range (1-65535)
|
|
29
|
-
port =
|
|
30
|
-
parsedPort > 0 && parsedPort < 65_536 ? parsedPort : config.SERVER_PORT;
|
|
30
|
+
port = parsedPort > 0 && parsedPort < 65_536 ? parsedPort : SERVER_PORT;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
catch {
|
|
34
|
-
port =
|
|
34
|
+
port = SERVER_PORT;
|
|
35
35
|
}
|
|
36
36
|
return `${COOKIE_NAME}-${port}`;
|
|
37
37
|
}
|
package/dist/local-auth/core/generators/auth-module/templates/module/utils/session-cookie.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { FastifyRequest } from 'fastify';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { getConfig, isDevelopment } from '%configServiceImports';
|
|
6
6
|
|
|
7
7
|
const COOKIE_NAME = 'user-session';
|
|
8
8
|
|
|
@@ -17,9 +17,10 @@ const COOKIE_NAME = 'user-session';
|
|
|
17
17
|
export function getUserSessionCookieName(
|
|
18
18
|
headers: FastifyRequest['headers'],
|
|
19
19
|
): string {
|
|
20
|
-
if (
|
|
20
|
+
if (!isDevelopment()) {
|
|
21
21
|
return `__Host-${COOKIE_NAME}`;
|
|
22
22
|
}
|
|
23
|
+
const { SERVER_PORT } = getConfig();
|
|
23
24
|
// in development, localhost does not support the __Host prefix and should be scoped to port
|
|
24
25
|
// use origin/referer header to determine hostname because dev reverse proxies use origin/referer to signal the original host
|
|
25
26
|
const { origin, referer } = headers;
|
|
@@ -27,16 +28,15 @@ export function getUserSessionCookieName(
|
|
|
27
28
|
let port;
|
|
28
29
|
try {
|
|
29
30
|
if (!originalHost) {
|
|
30
|
-
port =
|
|
31
|
+
port = SERVER_PORT;
|
|
31
32
|
} else {
|
|
32
33
|
const url = new URL(originalHost);
|
|
33
34
|
const parsedPort = Number.parseInt(url.port, 10);
|
|
34
35
|
// Validate port is in valid range (1-65535)
|
|
35
|
-
port =
|
|
36
|
-
parsedPort > 0 && parsedPort < 65_536 ? parsedPort : config.SERVER_PORT;
|
|
36
|
+
port = parsedPort > 0 && parsedPort < 65_536 ? parsedPort : SERVER_PORT;
|
|
37
37
|
}
|
|
38
38
|
} catch {
|
|
39
|
-
port =
|
|
39
|
+
port = SERVER_PORT;
|
|
40
40
|
}
|
|
41
41
|
return `${COOKIE_NAME}-${port}`;
|
|
42
42
|
}
|