@nauth-toolkit/mfa-sms 0.1.3
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 +90 -0
- package/README.md +30 -0
- package/dist/nestjs/index.d.ts +4 -0
- package/dist/nestjs/index.d.ts.map +1 -0
- package/dist/nestjs/index.js +22 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/nestjs/sms-mfa.module.d.ts +10 -0
- package/dist/nestjs/sms-mfa.module.d.ts.map +1 -0
- package/dist/nestjs/sms-mfa.module.js +58 -0
- package/dist/nestjs/sms-mfa.module.js.map +1 -0
- package/dist/src/dto/mfa.dto.d.ts +143 -0
- package/dist/src/dto/mfa.dto.d.ts.map +1 -0
- package/dist/src/dto/mfa.dto.js +3 -0
- package/dist/src/dto/mfa.dto.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +21 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/sms-mfa-provider.service.d.ts +18 -0
- package/dist/src/sms-mfa-provider.service.d.ts.map +1 -0
- package/dist/src/sms-mfa-provider.service.js +157 -0
- package/dist/src/sms-mfa-provider.service.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
NAUTH TOOLKIT EARLY ACCESS LICENSE
|
|
2
|
+
Version 1.0 (December 2025)
|
|
3
|
+
|
|
4
|
+
================================================================================
|
|
5
|
+
FUTURE OPEN SOURCE NOTICE
|
|
6
|
+
================================================================================
|
|
7
|
+
NAuth Toolkit will transition to an open-source license (MIT or Apache 2.0) for
|
|
8
|
+
core authentication features once the project reaches production readiness.
|
|
9
|
+
|
|
10
|
+
This Early Access License is temporary and designed to:
|
|
11
|
+
• Allow developers to build with nauth-toolkit during preview/beta
|
|
12
|
+
• Provide clear expectations during the pre-release phase
|
|
13
|
+
• Enable feedback and real-world testing before GA
|
|
14
|
+
|
|
15
|
+
We're committed to keeping core auth free and open source. Premium features
|
|
16
|
+
(enterprise SSO, advanced compliance, hosted options) will be offered separately
|
|
17
|
+
under fair commercial terms.
|
|
18
|
+
|
|
19
|
+
================================================================================
|
|
20
|
+
EARLY ACCESS LICENSE TERMS
|
|
21
|
+
================================================================================
|
|
22
|
+
|
|
23
|
+
1. Grant of Use
|
|
24
|
+
You are granted a free, non-exclusive, non-transferable license to:
|
|
25
|
+
- Install and use nauth-toolkit packages in development, testing, staging,
|
|
26
|
+
and production environments
|
|
27
|
+
- Modify the code for your own internal use
|
|
28
|
+
- Deploy applications using nauth-toolkit to serve your users
|
|
29
|
+
|
|
30
|
+
You may NOT:
|
|
31
|
+
- Redistribute NAuth Toolkit as a standalone product or service
|
|
32
|
+
- Sell, sublicense, or offer NAuth Toolkit as part of a competing auth
|
|
33
|
+
platform or toolkit
|
|
34
|
+
- Remove or alter copyright notices
|
|
35
|
+
|
|
36
|
+
2. No Fees During Early Access
|
|
37
|
+
There are no license fees, subscription costs, or usage charges during the
|
|
38
|
+
Early Access period. You may use nauth-toolkit freely for commercial and
|
|
39
|
+
non-commercial purposes within the terms of this license.
|
|
40
|
+
|
|
41
|
+
3. Production Use
|
|
42
|
+
Production use is permitted but comes with standard early-access caveats:
|
|
43
|
+
- Features and APIs may change between preview releases
|
|
44
|
+
- Support is community-based (GitHub issues/discussions)
|
|
45
|
+
- No SLA or guaranteed uptime (you run it on your infrastructure)
|
|
46
|
+
|
|
47
|
+
We recommend thorough testing and having rollback plans for critical systems.
|
|
48
|
+
|
|
49
|
+
4. Future Transition
|
|
50
|
+
When nauth-toolkit releases v1.0 GA:
|
|
51
|
+
- Core packages will adopt an open-source license (MIT or Apache 2.0)
|
|
52
|
+
- Your existing deployments will continue to work
|
|
53
|
+
- Premium features (if any) will be clearly documented with separate licensing
|
|
54
|
+
- No forced upgrades or surprise fees
|
|
55
|
+
|
|
56
|
+
5. Ownership
|
|
57
|
+
NAuth Toolkit is developed and maintained by Noorix Digital Solutions.
|
|
58
|
+
You retain full ownership of your applications and data.
|
|
59
|
+
|
|
60
|
+
6. Data and Privacy
|
|
61
|
+
NAuth Toolkit runs in YOUR infrastructure and database. You control all data.
|
|
62
|
+
You are responsible for compliance with applicable data protection laws.
|
|
63
|
+
|
|
64
|
+
7. Disclaimer of Warranty
|
|
65
|
+
THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
66
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
67
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
68
|
+
|
|
69
|
+
8. Limitation of Liability
|
|
70
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
|
|
71
|
+
SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES, INCLUDING BUT NOT LIMITED TO LOSS
|
|
72
|
+
OF PROFITS, REVENUE, DATA, OR USE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
73
|
+
DAMAGES.
|
|
74
|
+
|
|
75
|
+
9. Termination
|
|
76
|
+
This license remains in effect until:
|
|
77
|
+
- You stop using nauth-toolkit, or
|
|
78
|
+
- The project transitions to open source (at which point the new license applies)
|
|
79
|
+
|
|
80
|
+
If you breach these terms, your license terminates and you must stop using the
|
|
81
|
+
software.
|
|
82
|
+
|
|
83
|
+
10. Contact and Support
|
|
84
|
+
- Documentation: https://nauth.dev
|
|
85
|
+
- Issues/Discussions: GitHub (when public repository launches)
|
|
86
|
+
- Commercial inquiries: Contact admin@noorix.com
|
|
87
|
+
|
|
88
|
+
================================================================================
|
|
89
|
+
Thank you for being an early adopter. Your feedback shapes the future of NAuth.
|
|
90
|
+
================================================================================
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# @nauth-toolkit/mfa-sms
|
|
2
|
+
|
|
3
|
+
SMS MFA provider for nauth-toolkit
|
|
4
|
+
|
|
5
|
+
## ⚠️ Preview Release Notice
|
|
6
|
+
|
|
7
|
+
**This is a preview release for internal testing. Do not use in production yet.**
|
|
8
|
+
|
|
9
|
+
This package is part of nauth-toolkit and is currently in early access/preview. Features and APIs may change between releases. For production use, please wait for the stable v1.0 release.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @nauth-toolkit/mfa-sms@preview
|
|
15
|
+
# or
|
|
16
|
+
yarn add @nauth-toolkit/mfa-sms@preview
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## License
|
|
20
|
+
|
|
21
|
+
See LICENSE file in the package root for full license terms.
|
|
22
|
+
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
Full documentation: https://nauth.dev
|
|
26
|
+
|
|
27
|
+
## Support
|
|
28
|
+
|
|
29
|
+
- Issues/Discussions: GitHub (when repository is public)
|
|
30
|
+
- Documentation: https://nauth.dev
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../nestjs/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,cAAc,iCAAiC,CAAC;AAChD,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.SMSMFAModule = void 0;
|
|
18
|
+
var sms_mfa_module_1 = require("./sms-mfa.module");
|
|
19
|
+
Object.defineProperty(exports, "SMSMFAModule", { enumerable: true, get: function () { return sms_mfa_module_1.SMSMFAModule; } });
|
|
20
|
+
__exportStar(require("../src/sms-mfa-provider.service"), exports);
|
|
21
|
+
__exportStar(require("../src/dto/mfa.dto"), exports);
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../nestjs/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAMA,mDAAgD;AAAvC,8GAAA,YAAY,OAAA;AAGrB,kEAAgD;AAChD,qDAAmC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { SMSMFAProviderService } from '../src/sms-mfa-provider.service';
|
|
3
|
+
import { MFAService } from '@nauth-toolkit/core';
|
|
4
|
+
export declare class SMSMFAModule implements OnModuleInit {
|
|
5
|
+
private readonly smsMFAProvider;
|
|
6
|
+
private readonly mfaService;
|
|
7
|
+
constructor(smsMFAProvider: SMSMFAProviderService, mfaService: MFAService);
|
|
8
|
+
onModuleInit(): void;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=sms-mfa.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms-mfa.module.d.ts","sourceRoot":"","sources":["../../nestjs/sms-mfa.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EAAE,UAAU,EAAyE,MAAM,qBAAqB,CAAC;AA0BxH,qBA2Ca,YAAa,YAAW,YAAY;IAE7C,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,cAAc,EAAE,qBAAqB,EACrC,UAAU,EAAE,UAAU;IAMzC,YAAY,IAAI,IAAI;CAMrB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SMSMFAModule = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const sms_mfa_provider_service_1 = require("../src/sms-mfa-provider.service");
|
|
15
|
+
const core_1 = require("@nauth-toolkit/core");
|
|
16
|
+
const internal_1 = require("@nauth-toolkit/core/internal");
|
|
17
|
+
let SMSMFAModule = class SMSMFAModule {
|
|
18
|
+
smsMFAProvider;
|
|
19
|
+
mfaService;
|
|
20
|
+
constructor(smsMFAProvider, mfaService) {
|
|
21
|
+
this.smsMFAProvider = smsMFAProvider;
|
|
22
|
+
this.mfaService = mfaService;
|
|
23
|
+
}
|
|
24
|
+
onModuleInit() {
|
|
25
|
+
if (!this.mfaService) {
|
|
26
|
+
throw new Error('MFAService is not available. Ensure AuthModule.forRoot() is imported before SMSMFAModule.');
|
|
27
|
+
}
|
|
28
|
+
this.mfaService.registerProvider(this.smsMFAProvider);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
exports.SMSMFAModule = SMSMFAModule;
|
|
32
|
+
exports.SMSMFAModule = SMSMFAModule = __decorate([
|
|
33
|
+
(0, common_1.Module)({
|
|
34
|
+
providers: [
|
|
35
|
+
{
|
|
36
|
+
provide: sms_mfa_provider_service_1.SMSMFAProviderService,
|
|
37
|
+
useFactory: (mfaDeviceRepository, userRepository, config, logger, passwordService, phoneVerificationService, challengeService, auditService, clientInfoService) => {
|
|
38
|
+
return new sms_mfa_provider_service_1.SMSMFAProviderService(mfaDeviceRepository, userRepository, config, logger, passwordService, phoneVerificationService, challengeService, auditService, clientInfoService);
|
|
39
|
+
},
|
|
40
|
+
inject: [
|
|
41
|
+
'MFADeviceRepository',
|
|
42
|
+
'UserRepository',
|
|
43
|
+
'NAUTH_CONFIG',
|
|
44
|
+
'NAUTH_LOGGER',
|
|
45
|
+
{ token: internal_1.PasswordService, optional: true },
|
|
46
|
+
{ token: core_1.PhoneVerificationService, optional: true },
|
|
47
|
+
{ token: 'ChallengeService', optional: true },
|
|
48
|
+
{ token: internal_1.AuthAuditService, optional: true },
|
|
49
|
+
{ token: core_1.ClientInfoService, optional: true },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
exports: [sms_mfa_provider_service_1.SMSMFAProviderService],
|
|
54
|
+
}),
|
|
55
|
+
__metadata("design:paramtypes", [sms_mfa_provider_service_1.SMSMFAProviderService,
|
|
56
|
+
core_1.MFAService])
|
|
57
|
+
], SMSMFAModule);
|
|
58
|
+
//# sourceMappingURL=sms-mfa.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms-mfa.module.js","sourceRoot":"","sources":["../../nestjs/sms-mfa.module.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAsD;AACtD,8EAAwE;AAExE,8CAAwH;AAExH,2DAA6G;AAmEtG,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEJ;IACA;IAFnB,YACmB,cAAqC,EACrC,UAAsB;QADtB,mBAAc,GAAd,cAAc,CAAuB;QACrC,eAAU,GAAV,UAAU,CAAY;IACtC,CAAC;IAKJ,YAAY;QACV,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAC;QAC/G,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACxD,CAAC;CACF,CAAA;AAfY,oCAAY;uBAAZ,YAAY;IA3CxB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE;YAET;gBACE,OAAO,EAAE,gDAAqB;gBAC9B,UAAU,EAAE,CACV,mBAA8C,EAC9C,cAAoC,EACpC,MAAmB,EACnB,MAAmB,EACnB,eAAgC,EAChC,wBAA8D,EAC9D,gBAAqB,EACrB,YAAiB,EACjB,iBAAsB,EACtB,EAAE;oBACF,OAAO,IAAI,gDAAqB,CAC9B,mBAAmB,EACnB,cAAc,EACd,MAAM,EACN,MAAM,EACN,eAAe,EACf,wBAAwB,EACxB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,CAClB,CAAC;gBACJ,CAAC;gBACD,MAAM,EAAE;oBACN,qBAAqB;oBACrB,gBAAgB;oBAChB,cAAc;oBACd,cAAc;oBACd,EAAE,KAAK,EAAE,0BAAe,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC1C,EAAE,KAAK,EAAE,+BAAwB,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACnD,EAAE,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC7C,EAAE,KAAK,EAAE,2BAAwB,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACnD,EAAE,KAAK,EAAE,wBAAiB,EAAE,QAAQ,EAAE,IAAI,EAAE;iBAC7C;aACF;SACF;QACD,OAAO,EAAE,CAAC,gDAAqB,CAAC;KACjC,CAAC;qCAGmC,gDAAqB;QACzB,iBAAU;GAH9B,YAAY,CAexB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
export interface MFAChallengeResponseDTO {
|
|
2
|
+
challengeName: 'MFA_REQUIRED';
|
|
3
|
+
session: string;
|
|
4
|
+
challengeParameters: {
|
|
5
|
+
availableMethods: Array<'totp' | 'sms' | 'passkey' | 'backup'>;
|
|
6
|
+
preferredMethod?: 'totp' | 'sms' | 'passkey';
|
|
7
|
+
maskedPhone?: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface VerifyMFACodeDTO {
|
|
11
|
+
session: string;
|
|
12
|
+
method: 'totp' | 'sms' | 'backup';
|
|
13
|
+
code: string;
|
|
14
|
+
trustDevice?: boolean;
|
|
15
|
+
deviceId?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface VerifyPasskeyDTO {
|
|
18
|
+
session: string;
|
|
19
|
+
credential: {
|
|
20
|
+
id: string;
|
|
21
|
+
rawId: string;
|
|
22
|
+
response: {
|
|
23
|
+
clientDataJSON: string;
|
|
24
|
+
authenticatorData: string;
|
|
25
|
+
signature: string;
|
|
26
|
+
userHandle?: string;
|
|
27
|
+
};
|
|
28
|
+
type: 'public-key';
|
|
29
|
+
};
|
|
30
|
+
trustDevice?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface SetupTOTPResponseDTO {
|
|
33
|
+
secret: string;
|
|
34
|
+
qrCode: string;
|
|
35
|
+
manualEntryKey: string;
|
|
36
|
+
issuer: string;
|
|
37
|
+
accountName: string;
|
|
38
|
+
}
|
|
39
|
+
export interface VerifyTOTPSetupDTO {
|
|
40
|
+
secret: string;
|
|
41
|
+
code: string;
|
|
42
|
+
deviceName?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface SetupSMSMFADTO {
|
|
45
|
+
phoneNumber: string;
|
|
46
|
+
deviceName?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface VerifySMSMFASetupDTO {
|
|
49
|
+
phoneNumber: string;
|
|
50
|
+
code: string;
|
|
51
|
+
}
|
|
52
|
+
export interface SendSMSMFACodeDTO {
|
|
53
|
+
session: string;
|
|
54
|
+
}
|
|
55
|
+
export interface SetupPasskeyResponseDTO {
|
|
56
|
+
options: {
|
|
57
|
+
challenge: string;
|
|
58
|
+
rp: {
|
|
59
|
+
name: string;
|
|
60
|
+
id: string;
|
|
61
|
+
};
|
|
62
|
+
user: {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
displayName: string;
|
|
66
|
+
};
|
|
67
|
+
pubKeyCredParams: Array<{
|
|
68
|
+
type: 'public-key';
|
|
69
|
+
alg: number;
|
|
70
|
+
}>;
|
|
71
|
+
timeout: number;
|
|
72
|
+
attestation: 'none' | 'indirect' | 'direct';
|
|
73
|
+
authenticatorSelection?: {
|
|
74
|
+
authenticatorAttachment?: 'platform' | 'cross-platform';
|
|
75
|
+
requireResidentKey?: boolean;
|
|
76
|
+
userVerification?: 'required' | 'preferred' | 'discouraged';
|
|
77
|
+
};
|
|
78
|
+
excludeCredentials?: Array<{
|
|
79
|
+
id: string;
|
|
80
|
+
type: 'public-key';
|
|
81
|
+
transports?: string[];
|
|
82
|
+
}>;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export interface VerifyPasskeySetupDTO {
|
|
86
|
+
credential: {
|
|
87
|
+
id: string;
|
|
88
|
+
rawId: string;
|
|
89
|
+
response: {
|
|
90
|
+
clientDataJSON: string;
|
|
91
|
+
attestationObject: string;
|
|
92
|
+
};
|
|
93
|
+
type: 'public-key';
|
|
94
|
+
};
|
|
95
|
+
deviceName?: string;
|
|
96
|
+
}
|
|
97
|
+
export interface GetPasskeyChallengeResponseDTO {
|
|
98
|
+
options: {
|
|
99
|
+
challenge: string;
|
|
100
|
+
timeout: number;
|
|
101
|
+
rpId: string;
|
|
102
|
+
allowCredentials: Array<{
|
|
103
|
+
id: string;
|
|
104
|
+
type: 'public-key';
|
|
105
|
+
transports?: string[];
|
|
106
|
+
}>;
|
|
107
|
+
userVerification: 'required' | 'preferred' | 'discouraged';
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export interface GenerateBackupCodesResponseDTO {
|
|
111
|
+
codes: string[];
|
|
112
|
+
generated: string;
|
|
113
|
+
}
|
|
114
|
+
export interface MFADeviceDTO {
|
|
115
|
+
id: number;
|
|
116
|
+
type: 'totp' | 'sms' | 'passkey';
|
|
117
|
+
name: string;
|
|
118
|
+
isActive: boolean;
|
|
119
|
+
isPrimary: boolean;
|
|
120
|
+
lastUsedAt?: string;
|
|
121
|
+
createdAt: string;
|
|
122
|
+
maskedPhone?: string;
|
|
123
|
+
}
|
|
124
|
+
export interface ListMFADevicesResponseDTO {
|
|
125
|
+
devices: MFADeviceDTO[];
|
|
126
|
+
hasBackupCodes: boolean;
|
|
127
|
+
}
|
|
128
|
+
export interface UpdateMFADeviceDTO {
|
|
129
|
+
name?: string;
|
|
130
|
+
isPrimary?: boolean;
|
|
131
|
+
}
|
|
132
|
+
export interface DisableMFADeviceDTO {
|
|
133
|
+
password: string;
|
|
134
|
+
}
|
|
135
|
+
export interface MFAStatusResponseDTO {
|
|
136
|
+
enabled: boolean;
|
|
137
|
+
required: boolean;
|
|
138
|
+
gracePeriodEnds?: string;
|
|
139
|
+
configuredMethods: Array<'totp' | 'sms' | 'passkey'>;
|
|
140
|
+
preferredMethod?: 'totp' | 'sms' | 'passkey';
|
|
141
|
+
hasBackupCodes: boolean;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=mfa.dto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mfa.dto.d.ts","sourceRoot":"","sources":["../../../src/dto/mfa.dto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mfa.dto.js","sourceRoot":"","sources":["../../../src/dto/mfa.dto.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.SMSMFAProviderService = void 0;
|
|
18
|
+
var sms_mfa_provider_service_1 = require("./sms-mfa-provider.service");
|
|
19
|
+
Object.defineProperty(exports, "SMSMFAProviderService", { enumerable: true, get: function () { return sms_mfa_provider_service_1.SMSMFAProviderService; } });
|
|
20
|
+
__exportStar(require("./dto/mfa.dto"), exports);
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAOA,uEAAmE;AAA1D,iIAAA,qBAAqB,OAAA;AAC9B,gDAA8B"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Repository } from 'typeorm';
|
|
2
|
+
import { BaseMFADevice, BaseUser, IUser, NAuthConfig, NAuthLogger, PhoneVerificationService, MFAMethod } from '@nauth-toolkit/core';
|
|
3
|
+
import { BaseMFAProviderService } from '@nauth-toolkit/core/internal';
|
|
4
|
+
export declare class SMSMFAProviderService extends BaseMFAProviderService {
|
|
5
|
+
private readonly phoneVerificationService?;
|
|
6
|
+
readonly methodName = MFAMethod.SMS;
|
|
7
|
+
constructor(mfaDeviceRepository: Repository<BaseMFADevice>, userRepository: Repository<BaseUser>, config: NAuthConfig, logger: NAuthLogger, passwordService: unknown, phoneVerificationService?: PhoneVerificationService | undefined, challengeService?: unknown, auditService?: unknown, clientInfoService?: unknown);
|
|
8
|
+
setup(user: IUser, setupData?: unknown): Promise<{
|
|
9
|
+
deviceId: number;
|
|
10
|
+
autoCompleted: true;
|
|
11
|
+
} | {
|
|
12
|
+
maskedPhone: string;
|
|
13
|
+
}>;
|
|
14
|
+
verifySetup(user: IUser, verificationData: unknown, deviceName?: string): Promise<number>;
|
|
15
|
+
verify(user: IUser, code: unknown, deviceId?: number): Promise<boolean>;
|
|
16
|
+
sendChallenge(user: IUser): Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=sms-mfa-provider.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms-mfa-provider.service.d.ts","sourceRoot":"","sources":["../../src/sms-mfa-provider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EACL,aAAa,EACb,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAAW,EAGX,wBAAwB,EACxB,SAAS,EAGV,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAyBtE,qBAAa,qBAAsB,SAAQ,sBAAsB;IAS7D,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC;IAR5C,QAAQ,CAAC,UAAU,iBAAiB;gBAGlC,mBAAmB,EAAE,UAAU,CAAC,aAAa,CAAC,EAC9C,cAAc,EAAE,UAAU,CAAC,QAAQ,CAAC,EACpC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,WAAW,EACnB,eAAe,EAAE,OAAO,EACP,wBAAwB,CAAC,EAAE,wBAAwB,YAAA,EACpE,gBAAgB,CAAC,EAAE,OAAO,EAC1B,YAAY,CAAC,EAAE,OAAO,EACtB,iBAAiB,CAAC,EAAE,OAAO;IAmCvB,KAAK,CACT,IAAI,EAAE,KAAK,EACX,SAAS,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAkGzE,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwFzF,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkFvE,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;CA2ClD"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SMSMFAProviderService = void 0;
|
|
4
|
+
const core_1 = require("@nauth-toolkit/core");
|
|
5
|
+
const internal_1 = require("@nauth-toolkit/core/internal");
|
|
6
|
+
class SMSMFAProviderService extends internal_1.BaseMFAProviderService {
|
|
7
|
+
phoneVerificationService;
|
|
8
|
+
methodName = core_1.MFAMethod.SMS;
|
|
9
|
+
constructor(mfaDeviceRepository, userRepository, config, logger, passwordService, phoneVerificationService, challengeService, auditService, clientInfoService) {
|
|
10
|
+
super(mfaDeviceRepository, userRepository, config, logger, passwordService, challengeService, auditService, clientInfoService);
|
|
11
|
+
this.phoneVerificationService = phoneVerificationService;
|
|
12
|
+
}
|
|
13
|
+
async setup(user, setupData) {
|
|
14
|
+
this.logger?.log?.(`Setting up SMS MFA for user: ${user.sub}`);
|
|
15
|
+
if (!this.isMethodAllowed()) {
|
|
16
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'SMS MFA is not enabled', { feature: 'sms-mfa' });
|
|
17
|
+
}
|
|
18
|
+
const dto = setupData;
|
|
19
|
+
const userEntity = user;
|
|
20
|
+
const isPhoneVerified = userEntity.isPhoneVerified || false;
|
|
21
|
+
const phoneNumber = dto?.phoneNumber || userEntity.phone;
|
|
22
|
+
if (!phoneNumber) {
|
|
23
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.PHONE_REQUIRED, 'Phone number is required for SMS MFA setup. Please provide a phone number.');
|
|
24
|
+
}
|
|
25
|
+
if (isPhoneVerified) {
|
|
26
|
+
this.logger?.log?.(`Phone already verified for user ${user.sub}, auto-completing SMS MFA setup`);
|
|
27
|
+
const deviceId = await this.verifySetup(user, {
|
|
28
|
+
phoneNumber,
|
|
29
|
+
code: '',
|
|
30
|
+
}, dto?.deviceName);
|
|
31
|
+
return { deviceId, autoCompleted: true };
|
|
32
|
+
}
|
|
33
|
+
if (!this.phoneVerificationService) {
|
|
34
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'Phone verification service is not available. SMS provider must be configured.');
|
|
35
|
+
}
|
|
36
|
+
const sendDto = new core_1.SendVerificationSMSDTO();
|
|
37
|
+
sendDto.sub = user.sub;
|
|
38
|
+
const setupDataWithSession = setupData;
|
|
39
|
+
if (setupDataWithSession?.challengeSessionId) {
|
|
40
|
+
sendDto.challengeSessionId = setupDataWithSession.challengeSessionId;
|
|
41
|
+
this.logger?.debug?.(`Linking SMS verification token to challenge session: challengeSessionId=${setupDataWithSession.challengeSessionId}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.logger?.warn?.(`No challengeSessionId provided in setupData for SMS MFA setup. Token will not be linked to challenge session.`);
|
|
45
|
+
}
|
|
46
|
+
await this.phoneVerificationService.sendVerificationSMS(sendDto);
|
|
47
|
+
const maskedPhone = this.maskPhone(phoneNumber);
|
|
48
|
+
this.logger?.log?.(`SMS MFA code sent to: ${maskedPhone}`);
|
|
49
|
+
return { maskedPhone };
|
|
50
|
+
}
|
|
51
|
+
async verifySetup(user, verificationData, deviceName) {
|
|
52
|
+
this.logger?.log?.(`Verifying SMS MFA setup for user: ${user.sub}`);
|
|
53
|
+
const dto = verificationData;
|
|
54
|
+
const userEntity = user;
|
|
55
|
+
const userId = userEntity.id;
|
|
56
|
+
const userMfaEnabled = userEntity.mfaEnabled || false;
|
|
57
|
+
const isPhoneVerified = userEntity.isPhoneVerified || false;
|
|
58
|
+
if (!isPhoneVerified) {
|
|
59
|
+
if (!this.phoneVerificationService) {
|
|
60
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'Phone verification service is not available. SMS provider must be configured.');
|
|
61
|
+
}
|
|
62
|
+
if (!dto.code || dto.code.trim() === '') {
|
|
63
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'Verification code is required');
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const verifyDto = new core_1.VerifyPhoneWithCodeBySubDTO();
|
|
67
|
+
verifyDto.sub = user.sub;
|
|
68
|
+
verifyDto.code = dto.code;
|
|
69
|
+
await this.phoneVerificationService.verifyPhoneWithCodeBySub(verifyDto);
|
|
70
|
+
this.logger?.log?.(`Phone verified during SMS MFA setup for user ${user.sub} - phone is now marked as verified in database`);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
74
|
+
this.logger?.error?.(`Failed to verify phone during SMS MFA setup for user ${user.sub}: ${errorMessage}`, error);
|
|
75
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VERIFICATION_CODE_INVALID, 'Invalid SMS code');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.logger?.log?.(`Phone already verified for user ${user.sub}, skipping SMS code verification during MFA setup`);
|
|
80
|
+
}
|
|
81
|
+
const device = await this.createDevice(userId, {
|
|
82
|
+
name: deviceName || 'SMS Phone',
|
|
83
|
+
phoneNumber: dto.phoneNumber,
|
|
84
|
+
isActive: true,
|
|
85
|
+
isPrimary: !userMfaEnabled,
|
|
86
|
+
});
|
|
87
|
+
await this.enableMFAForUser(user);
|
|
88
|
+
this.logger?.log?.(`SMS MFA setup completed for user: ${user.sub}`);
|
|
89
|
+
return device.id;
|
|
90
|
+
}
|
|
91
|
+
async verify(user, code, deviceId) {
|
|
92
|
+
this.logger?.log?.(`Verifying SMS code for user: ${user.sub}`);
|
|
93
|
+
if (!this.phoneVerificationService) {
|
|
94
|
+
this.logger?.warn?.('SMS verification attempted but phone verification service is not available');
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const smsCode = code;
|
|
98
|
+
if (!smsCode || typeof smsCode !== 'string') {
|
|
99
|
+
this.logger?.warn?.('Invalid SMS code format');
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
const userEntity = user;
|
|
103
|
+
const userId = userEntity.id;
|
|
104
|
+
const isPhoneVerified = userEntity.isPhoneVerified || false;
|
|
105
|
+
const device = deviceId ? await this.findDevice(userId, deviceId) : null;
|
|
106
|
+
try {
|
|
107
|
+
const verifyDto = new core_1.VerifyPhoneWithCodeBySubDTO();
|
|
108
|
+
verifyDto.sub = user.sub;
|
|
109
|
+
verifyDto.code = smsCode;
|
|
110
|
+
await this.phoneVerificationService.verifyPhoneWithCodeBySub(verifyDto);
|
|
111
|
+
if (!isPhoneVerified) {
|
|
112
|
+
this.logger?.log?.(`SMS code verified and phone marked as verified during MFA for user: ${user.sub}`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.logger?.log?.(`SMS code verified for MFA (phone already verified) for user: ${user.sub}`);
|
|
116
|
+
}
|
|
117
|
+
if (device) {
|
|
118
|
+
await this.updateDeviceUsage(device.id);
|
|
119
|
+
}
|
|
120
|
+
this.logger?.log?.(`SMS code verified successfully for user: ${user.sub}`);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (error instanceof core_1.NAuthException) {
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
128
|
+
const errorCode = error?.code || 'UNKNOWN';
|
|
129
|
+
this.logger?.warn?.(`SMS code verification failed for user: ${user.sub}, code: ${smsCode}, error: ${errorCode} - ${errorMessage}`);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async sendChallenge(user) {
|
|
134
|
+
this.logger?.log?.(`Sending SMS MFA code for user: ${user.sub}`);
|
|
135
|
+
const userEntity = user;
|
|
136
|
+
const userId = userEntity.id;
|
|
137
|
+
const device = await this.findDevice(userId);
|
|
138
|
+
if (!device) {
|
|
139
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.NOT_FOUND, 'No SMS device registered', { deviceType: 'sms' });
|
|
140
|
+
}
|
|
141
|
+
const phoneNumber = device.phoneNumber || userEntity.phone;
|
|
142
|
+
if (!phoneNumber) {
|
|
143
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'No phone number found for SMS MFA. Please update your profile or re-setup SMS MFA.', { deviceType: 'sms' });
|
|
144
|
+
}
|
|
145
|
+
if (!this.phoneVerificationService) {
|
|
146
|
+
throw new core_1.NAuthException(core_1.AuthErrorCode.VALIDATION_FAILED, 'Phone verification service is not available. SMS provider must be configured.');
|
|
147
|
+
}
|
|
148
|
+
const sendDto = new core_1.SendVerificationSMSDTO();
|
|
149
|
+
sendDto.sub = user.sub;
|
|
150
|
+
sendDto.skipAlreadyVerifiedCheck = true;
|
|
151
|
+
await this.phoneVerificationService.sendVerificationSMS(sendDto);
|
|
152
|
+
this.logger?.log?.(`SMS MFA code sent for user: ${user.sub}`);
|
|
153
|
+
return this.maskPhone(phoneNumber);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.SMSMFAProviderService = SMSMFAProviderService;
|
|
157
|
+
//# sourceMappingURL=sms-mfa-provider.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sms-mfa-provider.service.js","sourceRoot":"","sources":["../../src/sms-mfa-provider.service.ts"],"names":[],"mappings":"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"}
|