@ackplus/nest-auth 1.1.15 → 1.1.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/README.md +82 -6
- package/package.json +1 -1
- package/src/lib/admin-console/static/index.html +4736 -432
- package/src/lib/auth/auth.module.d.ts.map +1 -1
- package/src/lib/auth/auth.module.js +2 -0
- package/src/lib/auth/controllers/auth.controller.d.ts +1 -0
- package/src/lib/auth/controllers/auth.controller.d.ts.map +1 -1
- package/src/lib/auth/controllers/auth.controller.js +19 -2
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.d.ts +1 -0
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.d.ts.map +1 -1
- package/src/lib/auth/dto/requests/verify-2fa.request.dto.js +8 -0
- package/src/lib/auth/entities/trusted-device.entity.d.ts +13 -0
- package/src/lib/auth/entities/trusted-device.entity.d.ts.map +1 -0
- package/src/lib/auth/entities/trusted-device.entity.js +51 -0
- package/src/lib/auth/index.d.ts +1 -0
- package/src/lib/auth/index.d.ts.map +1 -1
- package/src/lib/auth/index.js +1 -0
- package/src/lib/auth/services/auth.service.d.ts +1 -0
- package/src/lib/auth/services/auth.service.d.ts.map +1 -1
- package/src/lib/auth/services/auth.service.js +29 -1
- package/src/lib/auth/services/mfa.service.d.ts +5 -1
- package/src/lib/auth/services/mfa.service.d.ts.map +1 -1
- package/src/lib/auth/services/mfa.service.js +40 -1
- package/src/lib/auth.constants.d.ts +1 -0
- package/src/lib/auth.constants.d.ts.map +1 -1
- package/src/lib/auth.constants.js +2 -1
- package/src/lib/core/interfaces/mfa-options.interface.d.ts +2 -0
- package/src/lib/core/interfaces/mfa-options.interface.d.ts.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-auth/src/lib/auth/auth.module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-auth/src/lib/auth/auth.module.ts"],"names":[],"mappings":"AAuBA,qBAmCa,UAAU;CACtB"}
|
|
@@ -17,6 +17,7 @@ const user_entity_1 = require("../user/entities/user.entity");
|
|
|
17
17
|
const otp_entity_1 = require("./entities/otp.entity");
|
|
18
18
|
const mfa_secret_entity_1 = require("./entities/mfa-secret.entity");
|
|
19
19
|
const access_key_entity_1 = require("../user/entities/access-key.entity");
|
|
20
|
+
const trusted_device_entity_1 = require("./entities/trusted-device.entity");
|
|
20
21
|
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
21
22
|
const user_module_1 = require("../user/user.module");
|
|
22
23
|
const core_module_1 = require("../core/core.module");
|
|
@@ -36,6 +37,7 @@ exports.AuthModule = AuthModule = tslib_1.__decorate([
|
|
|
36
37
|
mfa_secret_entity_1.NestAuthMFASecret,
|
|
37
38
|
access_key_entity_1.NestAuthAccessKey,
|
|
38
39
|
identity_entity_1.NestAuthIdentity,
|
|
40
|
+
trusted_device_entity_1.NestAuthTrustedDevice,
|
|
39
41
|
]),
|
|
40
42
|
(0, common_1.forwardRef)(() => core_module_1.CoreModule),
|
|
41
43
|
(0, common_1.forwardRef)(() => user_module_1.UserModule),
|
|
@@ -43,6 +43,7 @@ export declare class AuthController {
|
|
|
43
43
|
protected handle2faResponse(res: Response, authResult: {
|
|
44
44
|
accessToken: string;
|
|
45
45
|
refreshToken: string;
|
|
46
|
+
trustToken?: string;
|
|
46
47
|
}): void;
|
|
47
48
|
signup(input: SignupRequestDto, res: Response): Promise<void>;
|
|
48
49
|
login(input: LoginRequestDto, res: Response): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/controllers/auth.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGnC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAG5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAW,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAErF,OAAO,EAAE,iCAAiC,EAAE,MAAM,wDAAwD,CAAC;AAC3G,OAAO,EAAE,gCAAgC,EAAE,MAAM,uDAAuD,CAAC;AACzG,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EAAE,+BAA+B,EAAE,MAAM,qDAAqD,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/controllers/auth.controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,7 @@ const send_email_verification_request_dto_1 = require("../dto/requests/send-emai
|
|
|
27
27
|
const verify_email_request_dto_1 = require("../dto/requests/verify-email.request.dto");
|
|
28
28
|
const client_config_service_1 = require("../services/client-config.service");
|
|
29
29
|
const client_config_response_dto_1 = require("../dto/responses/client-config.response.dto");
|
|
30
|
+
const auth_constants_1 = require("../../auth.constants");
|
|
30
31
|
let AuthController = class AuthController {
|
|
31
32
|
constructor(authService, cookieService, authConfig, clientConfigService) {
|
|
32
33
|
this.authService = authService;
|
|
@@ -69,12 +70,27 @@ let AuthController = class AuthController {
|
|
|
69
70
|
* Handle 2FA verification response based on configuration
|
|
70
71
|
*/
|
|
71
72
|
handle2faResponse(res, authResult) {
|
|
73
|
+
if (authResult.trustToken) {
|
|
74
|
+
const trustCookieName = auth_config_service_1.AuthConfigService.getOptions().mfa?.trustDeviceStorageName || auth_constants_1.NEST_AUTH_TRUST_DEVICE_KEY;
|
|
75
|
+
const duration = auth_config_service_1.AuthConfigService.getOptions().mfa?.trustedDeviceDuration || '30d';
|
|
76
|
+
// Convert duration to milliseconds for maxAge
|
|
77
|
+
const ms = require('ms');
|
|
78
|
+
const maxAge = typeof duration === 'string' ? ms(duration) : duration;
|
|
79
|
+
res.cookie(trustCookieName, authResult.trustToken, {
|
|
80
|
+
httpOnly: true,
|
|
81
|
+
secure: process.env.NODE_ENV === 'production',
|
|
82
|
+
sameSite: 'lax',
|
|
83
|
+
path: '/',
|
|
84
|
+
maxAge,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
72
87
|
if (this.isUsingCookies()) {
|
|
73
88
|
// Cookie mode: Set tokens in cookies, return success message
|
|
74
89
|
this.cookieService.setTokens(res, authResult.accessToken, authResult.refreshToken);
|
|
75
90
|
res.status(200).json({
|
|
76
|
-
message: '2FA verification successful'
|
|
91
|
+
message: '2FA verification successful',
|
|
77
92
|
// Note: No isRequiresMfa for 2FA verification (it's already verified)
|
|
93
|
+
trustToken: authResult.trustToken // Return trust token for mobile apps even in cookie mode
|
|
78
94
|
});
|
|
79
95
|
}
|
|
80
96
|
else {
|
|
@@ -82,7 +98,8 @@ let AuthController = class AuthController {
|
|
|
82
98
|
res.status(200).json({
|
|
83
99
|
message: '2FA verification successful',
|
|
84
100
|
accessToken: authResult.accessToken,
|
|
85
|
-
refreshToken: authResult.refreshToken
|
|
101
|
+
refreshToken: authResult.refreshToken,
|
|
102
|
+
trustToken: authResult.trustToken
|
|
86
103
|
});
|
|
87
104
|
}
|
|
88
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-2fa.request.dto.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/nest-auth/src/lib/auth/dto/requests/verify-2fa.request.dto.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,qBAAa,mBAAmB;IAQ5B,MAAM,EAAE,aAAa,CAAC;IAUtB,GAAG,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"verify-2fa.request.dto.d.ts","sourceRoot":"","sources":["../../../../../../../../packages/nest-auth/src/lib/auth/dto/requests/verify-2fa.request.dto.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,qBAAa,mBAAmB;IAQ5B,MAAM,EAAE,aAAa,CAAC;IAUtB,GAAG,EAAE,MAAM,CAAC;IAOZ,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B"}
|
|
@@ -29,3 +29,11 @@ tslib_1.__decorate([
|
|
|
29
29
|
(0, class_validator_1.IsNotEmpty)(),
|
|
30
30
|
tslib_1.__metadata("design:type", String)
|
|
31
31
|
], Verify2faRequestDto.prototype, "otp", void 0);
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, swagger_1.ApiProperty)({
|
|
34
|
+
description: 'Whether to trust this device for future logins',
|
|
35
|
+
example: true,
|
|
36
|
+
required: false,
|
|
37
|
+
}),
|
|
38
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
39
|
+
], Verify2faRequestDto.prototype, "rememberDevice", void 0);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NestAuthUser } from '../../user/entities/user.entity';
|
|
2
|
+
export declare class NestAuthTrustedDevice {
|
|
3
|
+
id: string;
|
|
4
|
+
userId: string;
|
|
5
|
+
user: NestAuthUser;
|
|
6
|
+
token: string;
|
|
7
|
+
userAgent: string;
|
|
8
|
+
ipAddress: string;
|
|
9
|
+
expiresAt: Date;
|
|
10
|
+
lastUsedAt: Date;
|
|
11
|
+
createdAt: Date;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=trusted-device.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted-device.entity.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/entities/trusted-device.entity.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAE/D,qBACa,qBAAqB;IAE9B,EAAE,EAAE,MAAM,CAAC;IAIX,MAAM,EAAE,MAAM,CAAC;IAIf,IAAI,EAAE,YAAY,CAAC;IAInB,KAAK,EAAE,MAAM,CAAC;IAGd,SAAS,EAAE,MAAM,CAAC;IAGlB,SAAS,EAAE,MAAM,CAAC;IAGlB,SAAS,EAAE,IAAI,CAAC;IAGhB,UAAU,EAAE,IAAI,CAAC;IAGjB,SAAS,EAAE,IAAI,CAAC;CACnB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NestAuthTrustedDevice = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const typeorm_1 = require("typeorm");
|
|
6
|
+
const user_entity_1 = require("../../user/entities/user.entity");
|
|
7
|
+
let NestAuthTrustedDevice = class NestAuthTrustedDevice {
|
|
8
|
+
};
|
|
9
|
+
exports.NestAuthTrustedDevice = NestAuthTrustedDevice;
|
|
10
|
+
tslib_1.__decorate([
|
|
11
|
+
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
|
12
|
+
tslib_1.__metadata("design:type", String)
|
|
13
|
+
], NestAuthTrustedDevice.prototype, "id", void 0);
|
|
14
|
+
tslib_1.__decorate([
|
|
15
|
+
(0, typeorm_1.Column)(),
|
|
16
|
+
(0, typeorm_1.Index)(),
|
|
17
|
+
tslib_1.__metadata("design:type", String)
|
|
18
|
+
], NestAuthTrustedDevice.prototype, "userId", void 0);
|
|
19
|
+
tslib_1.__decorate([
|
|
20
|
+
(0, typeorm_1.ManyToOne)(() => user_entity_1.NestAuthUser, { onDelete: 'CASCADE' }),
|
|
21
|
+
(0, typeorm_1.JoinColumn)({ name: 'userId' }),
|
|
22
|
+
tslib_1.__metadata("design:type", user_entity_1.NestAuthUser)
|
|
23
|
+
], NestAuthTrustedDevice.prototype, "user", void 0);
|
|
24
|
+
tslib_1.__decorate([
|
|
25
|
+
(0, typeorm_1.Column)(),
|
|
26
|
+
(0, typeorm_1.Index)(),
|
|
27
|
+
tslib_1.__metadata("design:type", String)
|
|
28
|
+
], NestAuthTrustedDevice.prototype, "token", void 0);
|
|
29
|
+
tslib_1.__decorate([
|
|
30
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
31
|
+
tslib_1.__metadata("design:type", String)
|
|
32
|
+
], NestAuthTrustedDevice.prototype, "userAgent", void 0);
|
|
33
|
+
tslib_1.__decorate([
|
|
34
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
35
|
+
tslib_1.__metadata("design:type", String)
|
|
36
|
+
], NestAuthTrustedDevice.prototype, "ipAddress", void 0);
|
|
37
|
+
tslib_1.__decorate([
|
|
38
|
+
(0, typeorm_1.Column)(),
|
|
39
|
+
tslib_1.__metadata("design:type", Date)
|
|
40
|
+
], NestAuthTrustedDevice.prototype, "expiresAt", void 0);
|
|
41
|
+
tslib_1.__decorate([
|
|
42
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
43
|
+
tslib_1.__metadata("design:type", Date)
|
|
44
|
+
], NestAuthTrustedDevice.prototype, "lastUsedAt", void 0);
|
|
45
|
+
tslib_1.__decorate([
|
|
46
|
+
(0, typeorm_1.CreateDateColumn)(),
|
|
47
|
+
tslib_1.__metadata("design:type", Date)
|
|
48
|
+
], NestAuthTrustedDevice.prototype, "createdAt", void 0);
|
|
49
|
+
exports.NestAuthTrustedDevice = NestAuthTrustedDevice = tslib_1.__decorate([
|
|
50
|
+
(0, typeorm_1.Entity)('nest_auth_trusted_devices')
|
|
51
|
+
], NestAuthTrustedDevice);
|
package/src/lib/auth/index.d.ts
CHANGED
|
@@ -38,4 +38,5 @@ export * from './dto/responses/mfa-status.response.dto';
|
|
|
38
38
|
export * from './dto/responses/client-config.response.dto';
|
|
39
39
|
export * from './entities/otp.entity';
|
|
40
40
|
export * from './entities/mfa-secret.entity';
|
|
41
|
+
export * from './entities/trusted-device.entity';
|
|
41
42
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-auth/src/lib/auth/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,cAAc,0CAA0C,CAAC;AAGzD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yCAAyC,CAAC;AACxD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AAGpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,kCAAkC,CAAC;AAGjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,0CAA0C,CAAC;AACzD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,sDAAsD,CAAC;AACrE,cAAc,uDAAuD,CAAC;AACtE,cAAc,0CAA0C,CAAC;AACzD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,mCAAmC,CAAC;AAClD,cAAc,0CAA0C,CAAC;AACzD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,4CAA4C,CAAC;AAG3D,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/nest-auth/src/lib/auth/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,cAAc,0CAA0C,CAAC;AAGzD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yCAAyC,CAAC;AACxD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qCAAqC,CAAC;AAGpD,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,kCAAkC,CAAC;AAGjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,8BAA8B,CAAC;AAG7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,0CAA0C,CAAC;AACzD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,sDAAsD,CAAC;AACrE,cAAc,uDAAuD,CAAC;AACtE,cAAc,0CAA0C,CAAC;AACzD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,uCAAuC,CAAC;AACtD,cAAc,0CAA0C,CAAC;AACzD,cAAc,uCAAuC,CAAC;AACtD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,mCAAmC,CAAC;AAClD,cAAc,0CAA0C,CAAC;AACzD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,4CAA4C,CAAC;AAG3D,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC"}
|
package/src/lib/auth/index.js
CHANGED
|
@@ -50,3 +50,4 @@ tslib_1.__exportStar(require("./dto/responses/client-config.response.dto"), expo
|
|
|
50
50
|
// Entities
|
|
51
51
|
tslib_1.__exportStar(require("./entities/otp.entity"), exports);
|
|
52
52
|
tslib_1.__exportStar(require("./entities/mfa-secret.entity"), exports);
|
|
53
|
+
tslib_1.__exportStar(require("./entities/trusted-device.entity"), exports);
|
|
@@ -41,6 +41,7 @@ export declare class AuthService {
|
|
|
41
41
|
verify2fa(input: Verify2faRequestDto): Promise<{
|
|
42
42
|
accessToken: string;
|
|
43
43
|
refreshToken: string;
|
|
44
|
+
trustToken: string;
|
|
44
45
|
}>;
|
|
45
46
|
send2faCode(userId: string, method: MFAMethodEnum): Promise<boolean>;
|
|
46
47
|
private handleSocialLogin;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/auth.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/auth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -174,7 +174,27 @@ let AuthService = class AuthService {
|
|
|
174
174
|
user = await this.getUserWithRolesAndPermissions(user.id);
|
|
175
175
|
const session = await this.sessionManager.createSessionFromUser(user);
|
|
176
176
|
const tokens = await this.generateTokensFromSession(session);
|
|
177
|
-
|
|
177
|
+
let isRequiresMfa = await this.mfaService.isRequiresMfa(user.id);
|
|
178
|
+
// Check for trusted device cookie or header if MFA is required
|
|
179
|
+
if (isRequiresMfa) {
|
|
180
|
+
const trustCookieName = auth_config_service_1.AuthConfigService.getOptions().mfa?.trustDeviceStorageName || auth_constants_1.NEST_AUTH_TRUST_DEVICE_KEY;
|
|
181
|
+
const req = request_context_1.RequestContext.currentRequest();
|
|
182
|
+
let trustToken = req.cookies?.[trustCookieName];
|
|
183
|
+
// If not in cookie, check header
|
|
184
|
+
if (!trustToken) {
|
|
185
|
+
trustToken = req.headers[trustCookieName];
|
|
186
|
+
}
|
|
187
|
+
if (trustToken) {
|
|
188
|
+
const isTrusted = await this.mfaService.validateTrustedDevice(user.id, trustToken);
|
|
189
|
+
if (isTrusted) {
|
|
190
|
+
isRequiresMfa = false;
|
|
191
|
+
// Update session to indicate MFA is verified by trust
|
|
192
|
+
await this.sessionManager.updateSession(session.id, {
|
|
193
|
+
data: { ...session.data, isMfaVerified: true }
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
178
198
|
// Emit login event
|
|
179
199
|
await this.eventEmitter.emitAsync(auth_constants_1.NestAuthEvents.LOGGED_IN, new user_logged_in_event_1.UserLoggedInEvent({
|
|
180
200
|
user,
|
|
@@ -219,6 +239,13 @@ let AuthService = class AuthService {
|
|
|
219
239
|
}
|
|
220
240
|
});
|
|
221
241
|
const tokens = await this.generateTokensFromSession(payload);
|
|
242
|
+
let trustToken;
|
|
243
|
+
if (input.rememberDevice) {
|
|
244
|
+
const req = request_context_1.RequestContext.currentRequest();
|
|
245
|
+
const userAgent = req.headers['user-agent'] || '';
|
|
246
|
+
const ip = req.ip || req.socket.remoteAddress || '';
|
|
247
|
+
trustToken = await this.mfaService.createTrustedDevice(session.userId, userAgent, ip);
|
|
248
|
+
}
|
|
222
249
|
const user = await this.getUser();
|
|
223
250
|
// Emit 2FA verified event
|
|
224
251
|
this.debugLogger.debug('Emitting 2FA verified event', 'AuthService', { userId: user.id });
|
|
@@ -233,6 +260,7 @@ let AuthService = class AuthService {
|
|
|
233
260
|
return {
|
|
234
261
|
accessToken: tokens.accessToken,
|
|
235
262
|
refreshToken: tokens.refreshToken,
|
|
263
|
+
trustToken,
|
|
236
264
|
};
|
|
237
265
|
}
|
|
238
266
|
catch (error) {
|
|
@@ -4,13 +4,15 @@ import { MFAMethodEnum, MFAOptions } from '../../core/interfaces/mfa-options.int
|
|
|
4
4
|
import { NestAuthUser } from '../../user/entities/user.entity';
|
|
5
5
|
import { NestAuthOTP } from '../../auth/entities/otp.entity';
|
|
6
6
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
7
|
+
import { NestAuthTrustedDevice } from '../entities/trusted-device.entity';
|
|
7
8
|
export declare class MfaService {
|
|
8
9
|
private mfaSecretRepository;
|
|
9
10
|
private userRepository;
|
|
10
11
|
private otpRepository;
|
|
12
|
+
private trustedDeviceRepository;
|
|
11
13
|
private eventEmitter;
|
|
12
14
|
mfaConfig: MFAOptions;
|
|
13
|
-
constructor(mfaSecretRepository: Repository<NestAuthMFASecret>, userRepository: Repository<NestAuthUser>, otpRepository: Repository<NestAuthOTP>, eventEmitter: EventEmitter2);
|
|
15
|
+
constructor(mfaSecretRepository: Repository<NestAuthMFASecret>, userRepository: Repository<NestAuthUser>, otpRepository: Repository<NestAuthOTP>, trustedDeviceRepository: Repository<NestAuthTrustedDevice>, eventEmitter: EventEmitter2);
|
|
14
16
|
requireMfaEnabledForApp(throwError?: boolean): boolean;
|
|
15
17
|
private checkIsMfaEnabledForApp;
|
|
16
18
|
getVerifiedMethods(userId: string): Promise<MFAMethodEnum[]>;
|
|
@@ -43,5 +45,7 @@ export declare class MfaService {
|
|
|
43
45
|
}>;
|
|
44
46
|
getAvailableMethods(): MFAMethodEnum[];
|
|
45
47
|
hasRecoveryCode(userId: string): Promise<boolean>;
|
|
48
|
+
createTrustedDevice(userId: string, userAgent: string, ipAddress: string): Promise<string>;
|
|
49
|
+
validateTrustedDevice(userId: string, token: string): Promise<boolean>;
|
|
46
50
|
}
|
|
47
51
|
//# sourceMappingURL=mfa.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mfa.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/mfa.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAY,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG1E,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,6CAA6C,CAAC;AAExF,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAK7D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"mfa.service.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/auth/services/mfa.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,11 +19,14 @@ const auth_config_service_1 = require("../../core/services/auth-config.service")
|
|
|
19
19
|
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
20
20
|
const auth_constants_2 = require("../../auth.constants");
|
|
21
21
|
const two_factor_code_sent_event_1 = require("../events/two-factor-code-sent.event");
|
|
22
|
+
const trusted_device_entity_1 = require("../entities/trusted-device.entity");
|
|
23
|
+
const crypto_1 = require("crypto");
|
|
22
24
|
let MfaService = class MfaService {
|
|
23
|
-
constructor(mfaSecretRepository, userRepository, otpRepository, eventEmitter) {
|
|
25
|
+
constructor(mfaSecretRepository, userRepository, otpRepository, trustedDeviceRepository, eventEmitter) {
|
|
24
26
|
this.mfaSecretRepository = mfaSecretRepository;
|
|
25
27
|
this.userRepository = userRepository;
|
|
26
28
|
this.otpRepository = otpRepository;
|
|
29
|
+
this.trustedDeviceRepository = trustedDeviceRepository;
|
|
27
30
|
this.eventEmitter = eventEmitter;
|
|
28
31
|
this.mfaConfig = auth_config_service_1.AuthConfigService.getOptions().mfa;
|
|
29
32
|
}
|
|
@@ -104,6 +107,11 @@ let MfaService = class MfaService {
|
|
|
104
107
|
if (!expiresAtMs || isNaN(expiresAtMs) || expiresAtMs <= 0) {
|
|
105
108
|
throw new Error(`Invalid MFA configuration: otpExpiresIn '${this.mfaConfig.otpExpiresIn}' results in invalid duration`);
|
|
106
109
|
}
|
|
110
|
+
// Invalidate previous MFA OTPs for this user
|
|
111
|
+
await this.otpRepository.delete({
|
|
112
|
+
userId,
|
|
113
|
+
type: otp_interface_1.OTPTypeEnum.MFA
|
|
114
|
+
});
|
|
107
115
|
const otp = await this.otpRepository.create({
|
|
108
116
|
userId,
|
|
109
117
|
type: otp_interface_1.OTPTypeEnum.MFA,
|
|
@@ -317,6 +325,35 @@ let MfaService = class MfaService {
|
|
|
317
325
|
});
|
|
318
326
|
return Boolean(user?.mfaRecoveryCode);
|
|
319
327
|
}
|
|
328
|
+
async createTrustedDevice(userId, userAgent, ipAddress) {
|
|
329
|
+
this.requireMfaEnabledForApp(true);
|
|
330
|
+
const token = (0, crypto_1.randomBytes)(32).toString('hex');
|
|
331
|
+
const duration = this.mfaConfig.trustedDeviceDuration || '30d';
|
|
332
|
+
const expiresAtMs = typeof duration === 'string' ? (0, ms_1.default)(duration) : duration;
|
|
333
|
+
await this.trustedDeviceRepository.save({
|
|
334
|
+
userId,
|
|
335
|
+
token,
|
|
336
|
+
userAgent,
|
|
337
|
+
ipAddress,
|
|
338
|
+
expiresAt: new Date(Date.now() + expiresAtMs),
|
|
339
|
+
});
|
|
340
|
+
return token;
|
|
341
|
+
}
|
|
342
|
+
async validateTrustedDevice(userId, token) {
|
|
343
|
+
if (!token)
|
|
344
|
+
return false;
|
|
345
|
+
const device = await this.trustedDeviceRepository.findOne({
|
|
346
|
+
where: { userId, token },
|
|
347
|
+
});
|
|
348
|
+
if (!device)
|
|
349
|
+
return false;
|
|
350
|
+
if (device.expiresAt < new Date()) {
|
|
351
|
+
await this.trustedDeviceRepository.remove(device);
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
await this.trustedDeviceRepository.update(device.id, { lastUsedAt: new Date() });
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
320
357
|
};
|
|
321
358
|
exports.MfaService = MfaService;
|
|
322
359
|
exports.MfaService = MfaService = tslib_1.__decorate([
|
|
@@ -324,7 +361,9 @@ exports.MfaService = MfaService = tslib_1.__decorate([
|
|
|
324
361
|
tslib_1.__param(0, (0, typeorm_1.InjectRepository)(mfa_secret_entity_1.NestAuthMFASecret)),
|
|
325
362
|
tslib_1.__param(1, (0, typeorm_1.InjectRepository)(user_entity_1.NestAuthUser)),
|
|
326
363
|
tslib_1.__param(2, (0, typeorm_1.InjectRepository)(otp_entity_1.NestAuthOTP)),
|
|
364
|
+
tslib_1.__param(3, (0, typeorm_1.InjectRepository)(trusted_device_entity_1.NestAuthTrustedDevice)),
|
|
327
365
|
tslib_1.__metadata("design:paramtypes", [typeorm_2.Repository,
|
|
366
|
+
typeorm_2.Repository,
|
|
328
367
|
typeorm_2.Repository,
|
|
329
368
|
typeorm_2.Repository,
|
|
330
369
|
event_emitter_1.EventEmitter2])
|
|
@@ -17,6 +17,7 @@ export declare const REFRESH_TOKEN_INVALID = "REFRESH_TOKEN_INVALID";
|
|
|
17
17
|
export declare const REFRESH_TOKEN_EXPIRED = "REFRESH_TOKEN_EXPIRED";
|
|
18
18
|
export declare const ACCESS_TOKEN_COOKIE_NAME = "accessToken";
|
|
19
19
|
export declare const REFRESH_TOKEN_COOKIE_NAME = "refreshToken";
|
|
20
|
+
export declare const NEST_AUTH_TRUST_DEVICE_KEY = "nest_auth_device_trust";
|
|
20
21
|
export declare const DEFAULT_GUARD_NAME = "web";
|
|
21
22
|
export declare const NestAuthEvents: {
|
|
22
23
|
readonly EMAIL_VERIFICATION_REQUESTED: "email.verification.requested";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.constants.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-auth/src/lib/auth.constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,kCAAkC,CAAC;AACnE,eAAO,MAAM,gCAAgC,qCAAqC,CAAC;AAInF,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AACvC,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAC7C,eAAO,MAAM,sBAAsB,aAAa,CAAC;AACjD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAC7C,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAI3C,eAAO,MAAM,6BAA6B,mBAAmB,CAAC;AAC9D,eAAO,MAAM,2BAA2B,iBAAiB,CAAC;AAC1D,eAAO,MAAM,0BAA0B,gBAAgB,CAAC;AACxD,eAAO,MAAM,oCAAoC,0BAA0B,CAAC;AAC5E,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAI7D,eAAO,MAAM,wBAAwB,gBAAgB,CAAC;AACtD,eAAO,MAAM,yBAAyB,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.constants.d.ts","sourceRoot":"","sources":["../../../../../packages/nest-auth/src/lib/auth.constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,kCAAkC,CAAC;AACnE,eAAO,MAAM,gCAAgC,qCAAqC,CAAC;AAInF,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AACvC,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAC7C,eAAO,MAAM,sBAAsB,aAAa,CAAC;AACjD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAC7C,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAI3C,eAAO,MAAM,6BAA6B,mBAAmB,CAAC;AAC9D,eAAO,MAAM,2BAA2B,iBAAiB,CAAC;AAC1D,eAAO,MAAM,0BAA0B,gBAAgB,CAAC;AACxD,eAAO,MAAM,oCAAoC,0BAA0B,CAAC;AAC5E,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAI7D,eAAO,MAAM,wBAAwB,gBAAgB,CAAC;AACtD,eAAO,MAAM,yBAAyB,iBAAiB,CAAC;AAExD,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AAGnE,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAGxC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;CA6BjB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NestAuthEvents = exports.DEFAULT_GUARD_NAME = exports.REFRESH_TOKEN_COOKIE_NAME = exports.ACCESS_TOKEN_COOKIE_NAME = exports.REFRESH_TOKEN_EXPIRED = exports.REFRESH_TOKEN_INVALID = exports.USER_NOT_ACTIVE_ERROR = exports.SESSION_NOT_FOUND_ERROR = exports.INVALID_REFRESH_TOKEN_EXCEPTION_CODE = exports.INVALID_MFA_EXCEPTION_CODE = exports.UNAUTHORIZED_EXCEPTION_CODE = exports.USER_NOT_FOUND_EXCEPTION_CODE = exports.PHONE_AUTH_PROVIDER = exports.EMAIL_AUTH_PROVIDER = exports.GITHUB_AUTH_PROVIDER = exports.APPLE_AUTH_PROVIDER = exports.FACEBOOK_AUTH_PROVIDER = exports.GOOGLE_AUTH_PROVIDER = exports.JWT_AUTH_PROVIDER = exports.NEST_AUTH_ASYNC_OPTIONS_PROVIDER = exports.AUTH_MODULE_OPTIONS = void 0;
|
|
3
|
+
exports.NestAuthEvents = exports.DEFAULT_GUARD_NAME = exports.NEST_AUTH_TRUST_DEVICE_KEY = exports.REFRESH_TOKEN_COOKIE_NAME = exports.ACCESS_TOKEN_COOKIE_NAME = exports.REFRESH_TOKEN_EXPIRED = exports.REFRESH_TOKEN_INVALID = exports.USER_NOT_ACTIVE_ERROR = exports.SESSION_NOT_FOUND_ERROR = exports.INVALID_REFRESH_TOKEN_EXCEPTION_CODE = exports.INVALID_MFA_EXCEPTION_CODE = exports.UNAUTHORIZED_EXCEPTION_CODE = exports.USER_NOT_FOUND_EXCEPTION_CODE = exports.PHONE_AUTH_PROVIDER = exports.EMAIL_AUTH_PROVIDER = exports.GITHUB_AUTH_PROVIDER = exports.APPLE_AUTH_PROVIDER = exports.FACEBOOK_AUTH_PROVIDER = exports.GOOGLE_AUTH_PROVIDER = exports.JWT_AUTH_PROVIDER = exports.NEST_AUTH_ASYNC_OPTIONS_PROVIDER = exports.AUTH_MODULE_OPTIONS = void 0;
|
|
4
4
|
exports.AUTH_MODULE_OPTIONS = 'NEST_AUTH_AUTH_MODULE_OPTIONS';
|
|
5
5
|
exports.NEST_AUTH_ASYNC_OPTIONS_PROVIDER = 'NEST_AUTH_ASYNC_OPTIONS_PROVIDER';
|
|
6
6
|
// Provider tokens
|
|
@@ -23,6 +23,7 @@ exports.REFRESH_TOKEN_EXPIRED = 'REFRESH_TOKEN_EXPIRED';
|
|
|
23
23
|
// Auth Cookie Names
|
|
24
24
|
exports.ACCESS_TOKEN_COOKIE_NAME = 'accessToken';
|
|
25
25
|
exports.REFRESH_TOKEN_COOKIE_NAME = 'refreshToken';
|
|
26
|
+
exports.NEST_AUTH_TRUST_DEVICE_KEY = 'nest_auth_device_trust';
|
|
26
27
|
// Default values
|
|
27
28
|
exports.DEFAULT_GUARD_NAME = 'web';
|
|
28
29
|
// Events Const
|
|
@@ -17,6 +17,8 @@ export interface MFAOptions {
|
|
|
17
17
|
allowUserToggle?: boolean;
|
|
18
18
|
allowMethodSelection?: boolean;
|
|
19
19
|
otpExpiresIn?: string | number;
|
|
20
|
+
trustedDeviceDuration?: string | number;
|
|
21
|
+
trustDeviceStorageName?: string;
|
|
20
22
|
}
|
|
21
23
|
export declare enum MFAMethodEnum {
|
|
22
24
|
TOTP = "totp",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mfa-options.interface.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/interfaces/mfa-options.interface.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU;IAEvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAG1B,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,IAAI,CAAC,EAAE;QACH,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IAGF,GAAG,CAAC,EAAE;QACF,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;IAGF,KAAK,CAAC,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;IAGF,eAAe,CAAC,EAAE,OAAO,CAAC;IAG1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAG/B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"mfa-options.interface.d.ts","sourceRoot":"","sources":["../../../../../../../packages/nest-auth/src/lib/core/interfaces/mfa-options.interface.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU;IAEvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAGlB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAG1B,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,IAAI,CAAC,EAAE;QACH,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IAGF,GAAG,CAAC,EAAE;QACF,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;IAGF,KAAK,CAAC,EAAE;QACJ,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;IAGF,eAAe,CAAC,EAAE,OAAO,CAAC;IAG1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAG/B,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAG/B,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAGxC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,oBAAY,aAAa;IACrB,IAAI,SAAS;IACb,GAAG,QAAQ;IACX,KAAK,UAAU;CAClB"}
|