@ambushsoftworks/nestjs-auth-graphql 0.11.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +300 -0
- package/README.md +411 -3
- package/dist/auth.module.d.ts +15 -1
- package/dist/auth.module.d.ts.map +1 -1
- package/dist/auth.module.js +114 -16
- package/dist/auth.module.js.map +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/decorators/require-scopes.decorator.d.ts +2 -0
- package/dist/decorators/require-scopes.decorator.d.ts.map +1 -0
- package/dist/decorators/require-scopes.decorator.js +8 -0
- package/dist/decorators/require-scopes.decorator.js.map +1 -0
- package/dist/guards/csrf.guard.d.ts +2 -0
- package/dist/guards/csrf.guard.d.ts.map +1 -1
- package/dist/guards/csrf.guard.js +9 -2
- package/dist/guards/csrf.guard.js.map +1 -1
- package/dist/guards/scope.guard.d.ts +8 -0
- package/dist/guards/scope.guard.d.ts.map +1 -0
- package/dist/guards/scope.guard.js +53 -0
- package/dist/guards/scope.guard.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/interfaces/api-key-repository.interface.d.ts +3 -0
- package/dist/interfaces/api-key-repository.interface.d.ts.map +1 -1
- package/dist/interfaces/biometric-repository.interface.d.ts +29 -17
- package/dist/interfaces/biometric-repository.interface.d.ts.map +1 -1
- package/dist/interfaces/biometric-verifier.interface.d.ts +10 -0
- package/dist/interfaces/biometric-verifier.interface.d.ts.map +1 -0
- package/dist/interfaces/{magic-link-repository.interface.js → biometric-verifier.interface.js} +1 -1
- package/dist/interfaces/biometric-verifier.interface.js.map +1 -0
- package/dist/resolvers/base-auth.resolver.d.ts.map +1 -1
- package/dist/resolvers/base-auth.resolver.js +0 -15
- package/dist/resolvers/base-auth.resolver.js.map +1 -1
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js +10 -3
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/biometric-auth.service.d.ts +47 -17
- package/dist/services/biometric-auth.service.d.ts.map +1 -1
- package/dist/services/biometric-auth.service.js +109 -68
- package/dist/services/biometric-auth.service.js.map +1 -1
- package/dist/services/biometric-challenge.service.d.ts +27 -0
- package/dist/services/biometric-challenge.service.d.ts.map +1 -0
- package/dist/services/biometric-challenge.service.js +116 -0
- package/dist/services/biometric-challenge.service.js.map +1 -0
- package/dist/services/biometric-verification.service.d.ts.map +1 -1
- package/dist/services/biometric-verification.service.js +4 -0
- package/dist/services/biometric-verification.service.js.map +1 -1
- package/dist/services/verification.service.d.ts +2 -1
- package/dist/services/verification.service.d.ts.map +1 -1
- package/dist/services/verification.service.js +38 -8
- package/dist/services/verification.service.js.map +1 -1
- package/dist/strategies/api-key.strategy.d.ts +6 -1
- package/dist/strategies/api-key.strategy.d.ts.map +1 -1
- package/dist/strategies/api-key.strategy.js +40 -6
- package/dist/strategies/api-key.strategy.js.map +1 -1
- package/dist/strategies/external-jwt.strategy.d.ts +19 -0
- package/dist/strategies/external-jwt.strategy.d.ts.map +1 -0
- package/dist/strategies/external-jwt.strategy.js +124 -0
- package/dist/strategies/external-jwt.strategy.js.map +1 -0
- package/dist/strategies/jwt.strategy.d.ts.map +1 -1
- package/dist/strategies/jwt.strategy.js +1 -0
- package/dist/strategies/jwt.strategy.js.map +1 -1
- package/dist/test-utils/mock-repositories.d.ts.map +1 -1
- package/dist/test-utils/mock-repositories.js +8 -7
- package/dist/test-utils/mock-repositories.js.map +1 -1
- package/dist/utils/provider-helpers.d.ts +6 -0
- package/dist/utils/provider-helpers.d.ts.map +1 -1
- package/dist/utils/provider-helpers.js +4 -0
- package/dist/utils/provider-helpers.js.map +1 -1
- package/dist/utils/verification-base-url.d.ts +2 -0
- package/dist/utils/verification-base-url.d.ts.map +1 -0
- package/dist/utils/verification-base-url.js +19 -0
- package/dist/utils/verification-base-url.js.map +1 -0
- package/dist/verifiers/es256-device-key.verifier.d.ts +14 -0
- package/dist/verifiers/es256-device-key.verifier.d.ts.map +1 -0
- package/dist/verifiers/es256-device-key.verifier.js +42 -0
- package/dist/verifiers/es256-device-key.verifier.js.map +1 -0
- package/package.json +8 -2
- package/dist/interfaces/magic-link-repository.interface.d.ts +0 -6
- package/dist/interfaces/magic-link-repository.interface.d.ts.map +0 -1
- package/dist/interfaces/magic-link-repository.interface.js.map +0 -1
- package/dist/interfaces/password-reset-strategy.interface.d.ts +0 -7
- package/dist/interfaces/password-reset-strategy.interface.d.ts.map +0 -1
- package/dist/interfaces/password-reset-strategy.interface.js +0 -3
- package/dist/interfaces/password-reset-strategy.interface.js.map +0 -1
- package/dist/repositories/noop-biometric.repository.d.ts +0 -26
- package/dist/repositories/noop-biometric.repository.d.ts.map +0 -1
- package/dist/repositories/noop-biometric.repository.js +0 -56
- package/dist/repositories/noop-biometric.repository.js.map +0 -1
- package/dist/repositories/noop-magic-link.repository.d.ts +0 -9
- package/dist/repositories/noop-magic-link.repository.d.ts.map +0 -1
- package/dist/repositories/noop-magic-link.repository.js +0 -37
- package/dist/repositories/noop-magic-link.repository.js.map +0 -1
- package/dist/strategies/magic-link.strategy.d.ts +0 -16
- package/dist/strategies/magic-link.strategy.d.ts.map +0 -1
- package/dist/strategies/magic-link.strategy.js +0 -80
- package/dist/strategies/magic-link.strategy.js.map +0 -1
- package/dist/strategies/verification-code.strategy.d.ts +0 -11
- package/dist/strategies/verification-code.strategy.d.ts.map +0 -1
- package/dist/strategies/verification-code.strategy.js +0 -44
- package/dist/strategies/verification-code.strategy.js.map +0 -1
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export interface IMagicLinkRepository {
|
|
2
|
-
storeMagicLink(userId: string, tokenHash: string, expiresAt: Date): Promise<void>;
|
|
3
|
-
validateMagicLink(userId: string, tokenHash: string): Promise<boolean>;
|
|
4
|
-
deleteMagicLink(userId: string): Promise<void>;
|
|
5
|
-
}
|
|
6
|
-
//# sourceMappingURL=magic-link-repository.interface.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"magic-link-repository.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/magic-link-repository.interface.ts"],"names":[],"mappings":"AAoDA,MAAM,WAAW,oBAAoB;IAkBnC,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,IAAI,CAAC,CAAC;IAyBjB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAiBvE,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"magic-link-repository.interface.js","sourceRoot":"","sources":["../../src/interfaces/magic-link-repository.interface.ts"],"names":[],"mappings":""}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface IPasswordResetStrategy {
|
|
2
|
-
generateResetToken(userId: string): Promise<string>;
|
|
3
|
-
validateResetToken(userId: string, token: string): Promise<boolean>;
|
|
4
|
-
getExpiryDuration(): number;
|
|
5
|
-
deleteResetToken(userId: string): Promise<void>;
|
|
6
|
-
}
|
|
7
|
-
//# sourceMappingURL=password-reset-strategy.interface.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"password-reset-strategy.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/password-reset-strategy.interface.ts"],"names":[],"mappings":"AA0DA,MAAM,WAAW,sBAAsB;IA0BrC,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IA0BpD,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAiBpE,iBAAiB,IAAI,MAAM,CAAC;IAmB5B,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"password-reset-strategy.interface.js","sourceRoot":"","sources":["../../src/interfaces/password-reset-strategy.interface.ts"],"names":[],"mappings":""}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { IBiometricRepository } from '../interfaces/biometric-repository.interface';
|
|
2
|
-
export declare class NoOpBiometricRepository implements IBiometricRepository {
|
|
3
|
-
private static warningShown;
|
|
4
|
-
private readonly logger;
|
|
5
|
-
private warnIfProduction;
|
|
6
|
-
storeBiometricCredential(userId: string, _credentialId: string, _publicKey: string, deviceName: string): Promise<void>;
|
|
7
|
-
getBiometricCredential(_credentialId: string): Promise<{
|
|
8
|
-
userId: string;
|
|
9
|
-
publicKey: string;
|
|
10
|
-
deviceName: string;
|
|
11
|
-
} | null>;
|
|
12
|
-
listBiometricCredentials(userId: string): Promise<Array<{
|
|
13
|
-
credentialId: string;
|
|
14
|
-
deviceName: string;
|
|
15
|
-
createdAt: Date;
|
|
16
|
-
}>>;
|
|
17
|
-
removeBiometricCredential(credentialId: string): Promise<void>;
|
|
18
|
-
storeBiometricChallenge(userId: string, _challenge: string, _expiresAt: Date): Promise<string>;
|
|
19
|
-
getBiometricChallenge(_challengeId: string): Promise<{
|
|
20
|
-
userId: string;
|
|
21
|
-
challenge: string;
|
|
22
|
-
expiresAt: Date;
|
|
23
|
-
} | null>;
|
|
24
|
-
markChallengeAsUsed(challengeId: string): Promise<void>;
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=noop-biometric.repository.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"noop-biometric.repository.d.ts","sourceRoot":"","sources":["../../src/repositories/noop-biometric.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAYpF,qBACa,uBAAwB,YAAW,oBAAoB;IAClE,OAAO,CAAC,MAAM,CAAC,YAAY,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IAEnE,OAAO,CAAC,gBAAgB;IAWlB,wBAAwB,CAC5B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAOV,sBAAsB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;QAC3D,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI,CAAC;IAOH,wBAAwB,CAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CACR,KAAK,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,CAAC,CACrE;IAOK,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9D,uBAAuB,CAC3B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,IAAI,GACf,OAAO,CAAC,MAAM,CAAC;IAOZ,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QACzD,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,IAAI,CAAC;KACjB,GAAG,IAAI,CAAC;IAOH,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK9D"}
|
|
@@ -1,56 +0,0 @@
|
|
|
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 NoOpBiometricRepository_1;
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.NoOpBiometricRepository = void 0;
|
|
11
|
-
const common_1 = require("@nestjs/common");
|
|
12
|
-
let NoOpBiometricRepository = NoOpBiometricRepository_1 = class NoOpBiometricRepository {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.logger = new common_1.Logger(NoOpBiometricRepository_1.name);
|
|
15
|
-
}
|
|
16
|
-
warnIfProduction() {
|
|
17
|
-
if (!NoOpBiometricRepository_1.warningShown && process.env.NODE_ENV === 'production') {
|
|
18
|
-
this.logger.warn('⚠️ NoOpBiometricRepository is being used in production! ' +
|
|
19
|
-
'Biometric authentication is DISABLED - credentials will NOT be stored. ' +
|
|
20
|
-
'Provide a real IBiometricRepository implementation in AuthModule.forRootAsync().');
|
|
21
|
-
NoOpBiometricRepository_1.warningShown = true;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
async storeBiometricCredential(userId, _credentialId, _publicKey, deviceName) {
|
|
25
|
-
this.warnIfProduction();
|
|
26
|
-
console.log(`[NoOpBiometricRepository] storeBiometricCredential called for userId: ${userId}, device: ${deviceName}`);
|
|
27
|
-
}
|
|
28
|
-
async getBiometricCredential(_credentialId) {
|
|
29
|
-
console.log(`[NoOpBiometricRepository] getBiometricCredential called for credentialId: ${_credentialId}`);
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
async listBiometricCredentials(userId) {
|
|
33
|
-
console.log(`[NoOpBiometricRepository] listBiometricCredentials called for userId: ${userId}`);
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
|
-
async removeBiometricCredential(credentialId) {
|
|
37
|
-
console.log(`[NoOpBiometricRepository] removeBiometricCredential called for credentialId: ${credentialId}`);
|
|
38
|
-
}
|
|
39
|
-
async storeBiometricChallenge(userId, _challenge, _expiresAt) {
|
|
40
|
-
console.log(`[NoOpBiometricRepository] storeBiometricChallenge called for userId: ${userId}`);
|
|
41
|
-
return 'noop-challenge-id';
|
|
42
|
-
}
|
|
43
|
-
async getBiometricChallenge(_challengeId) {
|
|
44
|
-
console.log(`[NoOpBiometricRepository] getBiometricChallenge called for challengeId: ${_challengeId}`);
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
async markChallengeAsUsed(challengeId) {
|
|
48
|
-
console.log(`[NoOpBiometricRepository] markChallengeAsUsed called for challengeId: ${challengeId}`);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
exports.NoOpBiometricRepository = NoOpBiometricRepository;
|
|
52
|
-
NoOpBiometricRepository.warningShown = false;
|
|
53
|
-
exports.NoOpBiometricRepository = NoOpBiometricRepository = NoOpBiometricRepository_1 = __decorate([
|
|
54
|
-
(0, common_1.Injectable)()
|
|
55
|
-
], NoOpBiometricRepository);
|
|
56
|
-
//# sourceMappingURL=noop-biometric.repository.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"noop-biometric.repository.js","sourceRoot":"","sources":["../../src/repositories/noop-biometric.repository.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAoD;AAc7C,IAAM,uBAAuB,+BAA7B,MAAM,uBAAuB;IAA7B;QAEY,WAAM,GAAG,IAAI,eAAM,CAAC,yBAAuB,CAAC,IAAI,CAAC,CAAC;IAgFrE,CAAC;IA9ES,gBAAgB;QACtB,IAAI,CAAC,yBAAuB,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YACnF,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,0DAA0D;gBAC1D,yEAAyE;gBACzE,kFAAkF,CACnF,CAAC;YACF,yBAAuB,CAAC,YAAY,GAAG,IAAI,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,wBAAwB,CAC5B,MAAc,EACd,aAAqB,EACrB,UAAkB,EAClB,UAAkB;QAElB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CACT,yEAAyE,MAAM,aAAa,UAAU,EAAE,CACzG,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,aAAqB;QAKhD,OAAO,CAAC,GAAG,CACT,6EAA6E,aAAa,EAAE,CAC7F,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,wBAAwB,CAC5B,MAAc;QAId,OAAO,CAAC,GAAG,CACT,yEAAyE,MAAM,EAAE,CAClF,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,YAAoB;QAClD,OAAO,CAAC,GAAG,CACT,gFAAgF,YAAY,EAAE,CAC/F,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,uBAAuB,CAC3B,MAAc,EACd,UAAkB,EAClB,UAAgB;QAEhB,OAAO,CAAC,GAAG,CACT,wEAAwE,MAAM,EAAE,CACjF,CAAC;QACF,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,YAAoB;QAK9C,OAAO,CAAC,GAAG,CACT,2EAA2E,YAAY,EAAE,CAC1F,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,WAAmB;QAC3C,OAAO,CAAC,GAAG,CACT,yEAAyE,WAAW,EAAE,CACvF,CAAC;IACJ,CAAC;;AAjFU,0DAAuB;AACnB,oCAAY,GAAG,KAAK,AAAR,CAAS;kCADzB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;GACA,uBAAuB,CAkFnC"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { IMagicLinkRepository } from '../interfaces/magic-link-repository.interface';
|
|
2
|
-
export declare class NoOpMagicLinkRepository implements IMagicLinkRepository {
|
|
3
|
-
private readonly logger;
|
|
4
|
-
private hasLoggedWarning;
|
|
5
|
-
storeMagicLink(userId: string, _tokenHash: string, expiresAt: Date): Promise<void>;
|
|
6
|
-
validateMagicLink(userId: string, _tokenHash: string): Promise<boolean>;
|
|
7
|
-
deleteMagicLink(userId: string): Promise<void>;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=noop-magic-link.repository.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"noop-magic-link.repository.d.ts","sourceRoot":"","sources":["../../src/repositories/noop-magic-link.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AA2BrF,qBACa,uBAAwB,YAAW,oBAAoB;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;IACnE,OAAO,CAAC,gBAAgB,CAAS;IAK3B,cAAc,CAClB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,IAAI,GACd,OAAO,CAAC,IAAI,CAAC;IAiBV,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQvE,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGrD"}
|
|
@@ -1,37 +0,0 @@
|
|
|
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 NoOpMagicLinkRepository_1;
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.NoOpMagicLinkRepository = void 0;
|
|
11
|
-
const common_1 = require("@nestjs/common");
|
|
12
|
-
let NoOpMagicLinkRepository = NoOpMagicLinkRepository_1 = class NoOpMagicLinkRepository {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.logger = new common_1.Logger(NoOpMagicLinkRepository_1.name);
|
|
15
|
-
this.hasLoggedWarning = false;
|
|
16
|
-
}
|
|
17
|
-
async storeMagicLink(userId, _tokenHash, expiresAt) {
|
|
18
|
-
if (!this.hasLoggedWarning) {
|
|
19
|
-
this.logger.warn('NoOpMagicLinkRepository is active - magic links will not work. ' +
|
|
20
|
-
'Provide a real implementation of IMagicLinkRepository for production.');
|
|
21
|
-
this.hasLoggedWarning = true;
|
|
22
|
-
}
|
|
23
|
-
this.logger.debug(`NoOp store magic link: userId=${userId}, expiresAt=${expiresAt.toISOString()}`);
|
|
24
|
-
}
|
|
25
|
-
async validateMagicLink(userId, _tokenHash) {
|
|
26
|
-
this.logger.debug(`NoOp validate magic link: userId=${userId} - always returns false`);
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
async deleteMagicLink(userId) {
|
|
30
|
-
this.logger.debug(`NoOp delete magic link: userId=${userId}`);
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
exports.NoOpMagicLinkRepository = NoOpMagicLinkRepository;
|
|
34
|
-
exports.NoOpMagicLinkRepository = NoOpMagicLinkRepository = NoOpMagicLinkRepository_1 = __decorate([
|
|
35
|
-
(0, common_1.Injectable)()
|
|
36
|
-
], NoOpMagicLinkRepository);
|
|
37
|
-
//# sourceMappingURL=noop-magic-link.repository.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"noop-magic-link.repository.js","sourceRoot":"","sources":["../../src/repositories/noop-magic-link.repository.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAoD;AA6B7C,IAAM,uBAAuB,+BAA7B,MAAM,uBAAuB;IAA7B;QACY,WAAM,GAAG,IAAI,eAAM,CAAC,yBAAuB,CAAC,IAAI,CAAC,CAAC;QAC3D,qBAAgB,GAAG,KAAK,CAAC;IAqCnC,CAAC;IAhCC,KAAK,CAAC,cAAc,CAClB,MAAc,EACd,UAAkB,EAClB,SAAe;QAEf,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,iEAAiE;gBACjE,uEAAuE,CACxE,CAAC;YACF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,iCAAiC,MAAM,eAAe,SAAS,CAAC,WAAW,EAAE,EAAE,CAChF,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,iBAAiB,CAAC,MAAc,EAAE,UAAkB;QACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,MAAM,yBAAyB,CAAC,CAAC;QACvF,OAAO,KAAK,CAAC;IACf,CAAC;IAKD,KAAK,CAAC,eAAe,CAAC,MAAc;QAClC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,MAAM,EAAE,CAAC,CAAC;IAChE,CAAC;CACF,CAAA;AAvCY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;GACA,uBAAuB,CAuCnC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { JwtService } from '@nestjs/jwt';
|
|
2
|
-
import { IPasswordResetStrategy } from '../interfaces/password-reset-strategy.interface';
|
|
3
|
-
import { IMagicLinkRepository } from '../interfaces/magic-link-repository.interface';
|
|
4
|
-
export declare class MagicLinkStrategy implements IPasswordResetStrategy {
|
|
5
|
-
private readonly jwtService;
|
|
6
|
-
private readonly repository;
|
|
7
|
-
private readonly expiryMs;
|
|
8
|
-
private readonly jwtSecret;
|
|
9
|
-
constructor(options: any, jwtService: JwtService, repository: IMagicLinkRepository);
|
|
10
|
-
generateResetToken(userId: string): Promise<string>;
|
|
11
|
-
validateResetToken(userId: string, token: string): Promise<boolean>;
|
|
12
|
-
getExpiryDuration(): number;
|
|
13
|
-
deleteResetToken(userId: string): Promise<void>;
|
|
14
|
-
private hashToken;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=magic-link.strategy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"magic-link.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/magic-link.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+CAA+C,CAAC;AAwDrF,qBACa,iBAAkB,YAAW,sBAAsB;IAM5D,OAAO,CAAC,QAAQ,CAAC,UAAU;IAE3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAP7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAGJ,OAAO,EAAE,GAAG,EACxB,UAAU,EAAE,UAAU,EAEtB,UAAU,EAAE,oBAAoB;IAY7C,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoCnD,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgCzE,iBAAiB,IAAI,MAAM;IAUrB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrD,OAAO,CAAC,SAAS;CAKlB"}
|
|
@@ -1,80 +0,0 @@
|
|
|
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
|
-
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
-
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.MagicLinkStrategy = void 0;
|
|
16
|
-
const common_1 = require("@nestjs/common");
|
|
17
|
-
const jwt_1 = require("@nestjs/jwt");
|
|
18
|
-
const constants_1 = require("../constants");
|
|
19
|
-
const crypto_1 = require("crypto");
|
|
20
|
-
let MagicLinkStrategy = class MagicLinkStrategy {
|
|
21
|
-
constructor(options, jwtService, repository) {
|
|
22
|
-
this.jwtService = jwtService;
|
|
23
|
-
this.repository = repository;
|
|
24
|
-
this.expiryMs = 60 * 60 * 1000;
|
|
25
|
-
this.jwtSecret = options.jwtSecret;
|
|
26
|
-
}
|
|
27
|
-
async generateResetToken(userId) {
|
|
28
|
-
const jti = (0, crypto_1.randomBytes)(32).toString('hex');
|
|
29
|
-
const payload = {
|
|
30
|
-
sub: userId,
|
|
31
|
-
type: 'password-reset',
|
|
32
|
-
jti,
|
|
33
|
-
iat: Math.floor(Date.now() / 1000),
|
|
34
|
-
exp: Math.floor((Date.now() + this.expiryMs) / 1000),
|
|
35
|
-
};
|
|
36
|
-
const token = await this.jwtService.signAsync(payload, {
|
|
37
|
-
secret: this.jwtSecret,
|
|
38
|
-
expiresIn: '1h',
|
|
39
|
-
});
|
|
40
|
-
const tokenHash = this.hashToken(token);
|
|
41
|
-
const expiresAt = new Date(Date.now() + this.expiryMs);
|
|
42
|
-
await this.repository.storeMagicLink(userId, tokenHash, expiresAt);
|
|
43
|
-
return token;
|
|
44
|
-
}
|
|
45
|
-
async validateResetToken(userId, token) {
|
|
46
|
-
try {
|
|
47
|
-
const payload = await this.jwtService.verifyAsync(token, { secret: this.jwtSecret });
|
|
48
|
-
if (payload.sub !== userId ||
|
|
49
|
-
payload.type !== 'password-reset' ||
|
|
50
|
-
!payload.jti) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
const tokenHash = this.hashToken(token);
|
|
54
|
-
const isValid = await this.repository.validateMagicLink(userId, tokenHash);
|
|
55
|
-
return isValid;
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
getExpiryDuration() {
|
|
62
|
-
return this.expiryMs;
|
|
63
|
-
}
|
|
64
|
-
async deleteResetToken(userId) {
|
|
65
|
-
await this.repository.deleteMagicLink(userId);
|
|
66
|
-
}
|
|
67
|
-
hashToken(token) {
|
|
68
|
-
const hmac = (0, crypto_1.createHmac)('sha256', this.jwtSecret);
|
|
69
|
-
hmac.update(token);
|
|
70
|
-
return hmac.digest('hex');
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
exports.MagicLinkStrategy = MagicLinkStrategy;
|
|
74
|
-
exports.MagicLinkStrategy = MagicLinkStrategy = __decorate([
|
|
75
|
-
(0, common_1.Injectable)(),
|
|
76
|
-
__param(0, (0, common_1.Inject)(constants_1.AUTH_MODULE_OPTIONS)),
|
|
77
|
-
__param(2, (0, common_1.Inject)('MAGIC_LINK_REPOSITORY')),
|
|
78
|
-
__metadata("design:paramtypes", [Object, jwt_1.JwtService, Object])
|
|
79
|
-
], MagicLinkStrategy);
|
|
80
|
-
//# sourceMappingURL=magic-link.strategy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"magic-link.strategy.js","sourceRoot":"","sources":["../../src/strategies/magic-link.strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { IPasswordResetStrategy } from '../interfaces/password-reset-strategy.interface';
|
|
2
|
-
import { VerificationService } from '../services/verification.service';
|
|
3
|
-
export declare class VerificationCodeStrategy implements IPasswordResetStrategy {
|
|
4
|
-
private readonly verificationService;
|
|
5
|
-
constructor(verificationService: VerificationService);
|
|
6
|
-
generateResetToken(userId: string): Promise<string>;
|
|
7
|
-
validateResetToken(userId: string, code: string): Promise<boolean>;
|
|
8
|
-
getExpiryDuration(): number;
|
|
9
|
-
deleteResetToken(userId: string): Promise<void>;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=verification-code.strategy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"verification-code.strategy.d.ts","sourceRoot":"","sources":["../../src/strategies/verification-code.strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AA4CvE,qBACa,wBAAyB,YAAW,sBAAsB;IACzD,OAAO,CAAC,QAAQ,CAAC,mBAAmB;gBAAnB,mBAAmB,EAAE,mBAAmB;IAS/D,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBnD,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBxE,iBAAiB,IAAI,MAAM;IAUrB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMtD"}
|
|
@@ -1,44 +0,0 @@
|
|
|
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.VerificationCodeStrategy = void 0;
|
|
13
|
-
const common_1 = require("@nestjs/common");
|
|
14
|
-
const verification_service_1 = require("../services/verification.service");
|
|
15
|
-
let VerificationCodeStrategy = class VerificationCodeStrategy {
|
|
16
|
-
constructor(verificationService) {
|
|
17
|
-
this.verificationService = verificationService;
|
|
18
|
-
}
|
|
19
|
-
async generateResetToken(userId) {
|
|
20
|
-
const code = await this.verificationService.generateCode(userId, 'password-reset');
|
|
21
|
-
return code;
|
|
22
|
-
}
|
|
23
|
-
async validateResetToken(userId, code) {
|
|
24
|
-
try {
|
|
25
|
-
await this.verificationService.validateCode(userId, 'password-reset', code);
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
getExpiryDuration() {
|
|
33
|
-
return 15 * 60 * 1000;
|
|
34
|
-
}
|
|
35
|
-
async deleteResetToken(userId) {
|
|
36
|
-
await this.verificationService.invalidateCode(userId, 'password-reset');
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
exports.VerificationCodeStrategy = VerificationCodeStrategy;
|
|
40
|
-
exports.VerificationCodeStrategy = VerificationCodeStrategy = __decorate([
|
|
41
|
-
(0, common_1.Injectable)(),
|
|
42
|
-
__metadata("design:paramtypes", [verification_service_1.VerificationService])
|
|
43
|
-
], VerificationCodeStrategy);
|
|
44
|
-
//# sourceMappingURL=verification-code.strategy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"verification-code.strategy.js","sourceRoot":"","sources":["../../src/strategies/verification-code.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,2EAAuE;AA6ChE,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IACnC,YAA6B,mBAAwC;QAAxC,wBAAmB,GAAnB,mBAAmB,CAAqB;IAAG,CAAC;IASzE,KAAK,CAAC,kBAAkB,CAAC,MAAc;QAIrC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,CACtD,MAAM,EACN,gBAAgB,CACjB,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAUD,KAAK,CAAC,kBAAkB,CAAC,MAAc,EAAE,IAAY;QACnD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,CACzC,MAAM,EACN,gBAAgB,EAChB,IAAI,CACL,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAMD,iBAAiB;QACf,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACxB,CAAC;IAQD,KAAK,CAAC,gBAAgB,CAAC,MAAc;QACnC,MAAM,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAC3C,MAAM,EACN,gBAAgB,CACjB,CAAC;IACJ,CAAC;CACF,CAAA;AAhEY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;qCAEuC,0CAAmB;GAD1D,wBAAwB,CAgEpC"}
|