@ambushsoftworks/nestjs-auth-graphql 0.12.0 → 0.15.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 +210 -0
- package/README.md +285 -1
- package/dist/auth.module.d.ts +9 -0
- package/dist/auth.module.d.ts.map +1 -1
- package/dist/auth.module.js +69 -4
- package/dist/auth.module.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/dist/interfaces/biometric-repository.interface.d.ts +30 -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/services/biometric-auth.service.d.ts +51 -17
- package/dist/services/biometric-auth.service.d.ts.map +1 -1
- package/dist/services/biometric-auth.service.js +121 -67
- 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/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/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
|
@@ -11,102 +11,156 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
+
var BiometricAuthService_1;
|
|
14
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
16
|
exports.BiometricAuthService = void 0;
|
|
16
17
|
const common_1 = require("@nestjs/common");
|
|
17
|
-
const
|
|
18
|
-
const refresh_token_service_1 = require("./refresh-token.service");
|
|
18
|
+
const crypto_1 = require("crypto");
|
|
19
19
|
const auth_logger_interface_1 = require("../interfaces/auth-logger.interface");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const constants_1 = require("../constants");
|
|
21
|
+
const biometric_challenge_service_1 = require("./biometric-challenge.service");
|
|
22
|
+
const auth_service_1 = require("./auth.service");
|
|
23
|
+
let BiometricAuthService = BiometricAuthService_1 = class BiometricAuthService {
|
|
24
|
+
constructor(biometricRepository, securityLogger, verifiers, challenges, authService, options) {
|
|
24
25
|
this.biometricRepository = biometricRepository;
|
|
25
26
|
this.securityLogger = securityLogger;
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
27
|
+
this.challenges = challenges;
|
|
28
|
+
this.authService = authService;
|
|
29
|
+
this.logger = new common_1.Logger(BiometricAuthService_1.name);
|
|
30
|
+
this.realmsEnabled = Boolean(options.realmExtractorInstance);
|
|
31
|
+
this.verifiersByAlgorithm = new Map(verifiers.map((v) => [v.algorithm, v]));
|
|
28
32
|
}
|
|
29
|
-
async
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
async enrolCredential(input) {
|
|
34
|
+
this.requireRealm(input.realm);
|
|
35
|
+
const algorithm = input.algorithm ?? this.defaultAlgorithm;
|
|
36
|
+
const verifier = this.verifiersByAlgorithm.get(algorithm);
|
|
37
|
+
if (!verifier) {
|
|
38
|
+
throw new common_1.UnauthorizedException(`No biometric verifier is configured for algorithm '${algorithm}'.`);
|
|
32
39
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
throw new common_1.UnauthorizedException('User not found');
|
|
40
|
+
if (!(await verifier.validatePublicKey(input.publicKey))) {
|
|
41
|
+
throw new common_1.UnauthorizedException(`The public key is not a valid '${algorithm}' key.`);
|
|
36
42
|
}
|
|
37
|
-
|
|
43
|
+
const record = {
|
|
44
|
+
credentialId: (0, crypto_1.randomUUID)(),
|
|
45
|
+
userId: input.userId,
|
|
46
|
+
publicKey: input.publicKey,
|
|
47
|
+
algorithm,
|
|
48
|
+
deviceName: input.deviceName,
|
|
49
|
+
...(input.realm !== undefined ? { realm: input.realm } : {}),
|
|
50
|
+
createdAt: new Date(),
|
|
51
|
+
lastUsedAt: null,
|
|
52
|
+
isActive: true,
|
|
53
|
+
...(input.metadata ? { metadata: input.metadata } : {}),
|
|
54
|
+
};
|
|
55
|
+
await this.biometricRepository.storeCredential(record);
|
|
38
56
|
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_ENROLLED, {
|
|
39
|
-
userId,
|
|
40
|
-
|
|
57
|
+
userId: input.userId,
|
|
58
|
+
credentialId: record.credentialId,
|
|
59
|
+
algorithm,
|
|
41
60
|
});
|
|
42
|
-
return
|
|
61
|
+
return this.summarise(record);
|
|
43
62
|
}
|
|
44
|
-
async
|
|
45
|
-
|
|
46
|
-
if (!user) {
|
|
47
|
-
throw new common_1.UnauthorizedException('User not found');
|
|
48
|
-
}
|
|
49
|
-
await this.userRepository.disableBiometric(userId);
|
|
50
|
-
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_DISABLED, {
|
|
51
|
-
userId,
|
|
52
|
-
});
|
|
53
|
-
return true;
|
|
63
|
+
async requestChallenge(credentialId, opts = {}) {
|
|
64
|
+
return this.challenges.issueChallenge(credentialId, opts);
|
|
54
65
|
}
|
|
55
|
-
async authenticateWithBiometric(
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
async authenticateWithBiometric(input, opts = {}) {
|
|
67
|
+
this.requireRealm(opts.realm);
|
|
68
|
+
const fail = (reason, credentialId) => {
|
|
69
|
+
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_LOGIN_FAILURE, {
|
|
70
|
+
credentialId,
|
|
71
|
+
ipAddress: opts.ipAddress,
|
|
72
|
+
realm: opts.realm,
|
|
73
|
+
reason,
|
|
74
|
+
});
|
|
75
|
+
throw new common_1.UnauthorizedException('Biometric authentication failed');
|
|
76
|
+
};
|
|
77
|
+
const challenge = await this.challenges.consumeChallenge(input.challengeId);
|
|
78
|
+
if (!challenge) {
|
|
79
|
+
return fail('challenge_unavailable', input.credentialId);
|
|
80
|
+
}
|
|
81
|
+
if (challenge.credentialId !== input.credentialId) {
|
|
82
|
+
return fail('challenge_credential_mismatch', input.credentialId);
|
|
83
|
+
}
|
|
84
|
+
const credential = await this.biometricRepository.getCredential(input.credentialId);
|
|
85
|
+
if (!credential) {
|
|
86
|
+
return fail('credential_unknown', input.credentialId);
|
|
58
87
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
throw new common_1.UnauthorizedException('Invalid biometric credentials');
|
|
88
|
+
if (!credential.isActive) {
|
|
89
|
+
return fail('credential_inactive', input.credentialId);
|
|
62
90
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
throw new common_1.UnauthorizedException('Biometric authentication not enabled');
|
|
91
|
+
if ((credential.realm ?? undefined) !== opts.realm) {
|
|
92
|
+
return fail('credential_realm_mismatch', input.credentialId);
|
|
66
93
|
}
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
-
|
|
94
|
+
const verifier = this.verifiersByAlgorithm.get(credential.algorithm);
|
|
95
|
+
if (!verifier) {
|
|
96
|
+
this.logger.error(`Credential ${input.credentialId} is enrolled under algorithm ` +
|
|
97
|
+
`'${credential.algorithm}', for which no verifier is configured. ` +
|
|
98
|
+
'Add it to biometric.verifiers, or deactivate the credential.');
|
|
99
|
+
return fail('verifier_missing', input.credentialId);
|
|
70
100
|
}
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
101
|
+
const valid = await verifier.verify({
|
|
102
|
+
publicKey: credential.publicKey,
|
|
103
|
+
challenge: challenge.challenge,
|
|
104
|
+
signature: input.signature,
|
|
74
105
|
});
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
if (!valid) {
|
|
107
|
+
return fail('signature_invalid', input.credentialId);
|
|
108
|
+
}
|
|
109
|
+
const session = await this.authService.issueAuthSession(credential.userId, opts.res, opts.realm);
|
|
110
|
+
void this.biometricRepository
|
|
111
|
+
.touchCredentialLastUsed(input.credentialId)
|
|
112
|
+
.catch((error) => {
|
|
113
|
+
this.logger.warn(`Recording last use of credential ${input.credentialId} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
81
114
|
});
|
|
82
|
-
await this.userRepository.updateLastBiometricLogin(userId);
|
|
83
115
|
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_LOGIN_SUCCESS, {
|
|
116
|
+
userId: credential.userId,
|
|
117
|
+
credentialId: input.credentialId,
|
|
118
|
+
ipAddress: opts.ipAddress,
|
|
119
|
+
realm: opts.realm,
|
|
120
|
+
});
|
|
121
|
+
return session;
|
|
122
|
+
}
|
|
123
|
+
async listCredentials(userId, realm) {
|
|
124
|
+
const credentials = await this.biometricRepository.listCredentials(userId, realm);
|
|
125
|
+
return credentials.filter((c) => c.isActive).map((c) => this.summarise(c));
|
|
126
|
+
}
|
|
127
|
+
async removeCredential(userId, credentialId) {
|
|
128
|
+
const credential = await this.biometricRepository.getCredential(credentialId);
|
|
129
|
+
if (!credential || credential.userId !== userId) {
|
|
130
|
+
throw new common_1.UnauthorizedException('Biometric credential not found');
|
|
131
|
+
}
|
|
132
|
+
await this.biometricRepository.deactivateCredential(credentialId);
|
|
133
|
+
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_DEVICE_REMOVED, {
|
|
84
134
|
userId,
|
|
135
|
+
credentialId,
|
|
85
136
|
});
|
|
86
|
-
return { accessToken, refreshToken };
|
|
87
137
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
throw new common_1.UnauthorizedException('User not found');
|
|
138
|
+
requireRealm(realm) {
|
|
139
|
+
if (this.realmsEnabled && (realm === undefined || realm === null)) {
|
|
140
|
+
throw new common_1.BadRequestException('Realm required');
|
|
92
141
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
142
|
+
}
|
|
143
|
+
get defaultAlgorithm() {
|
|
144
|
+
return this.verifiersByAlgorithm.keys().next().value;
|
|
145
|
+
}
|
|
146
|
+
summarise(record) {
|
|
96
147
|
return {
|
|
97
|
-
|
|
98
|
-
|
|
148
|
+
credentialId: record.credentialId,
|
|
149
|
+
deviceName: record.deviceName,
|
|
150
|
+
algorithm: record.algorithm,
|
|
151
|
+
createdAt: record.createdAt,
|
|
152
|
+
lastUsedAt: record.lastUsedAt,
|
|
99
153
|
};
|
|
100
154
|
}
|
|
101
155
|
};
|
|
102
156
|
exports.BiometricAuthService = BiometricAuthService;
|
|
103
|
-
exports.BiometricAuthService = BiometricAuthService = __decorate([
|
|
157
|
+
exports.BiometricAuthService = BiometricAuthService = BiometricAuthService_1 = __decorate([
|
|
104
158
|
(0, common_1.Injectable)(),
|
|
105
|
-
__param(0, (0, common_1.Inject)(
|
|
106
|
-
__param(1, (0, common_1.Inject)(
|
|
107
|
-
__param(2, (0, common_1.Inject)(
|
|
108
|
-
__param(
|
|
109
|
-
__metadata("design:paramtypes", [Object, Object,
|
|
110
|
-
|
|
159
|
+
__param(0, (0, common_1.Inject)(constants_1.BIOMETRIC_REPOSITORY)),
|
|
160
|
+
__param(1, (0, common_1.Inject)(constants_1.AUTH_LOGGER)),
|
|
161
|
+
__param(2, (0, common_1.Inject)(constants_1.BIOMETRIC_VERIFIERS)),
|
|
162
|
+
__param(5, (0, common_1.Inject)(constants_1.AUTH_MODULE_OPTIONS)),
|
|
163
|
+
__metadata("design:paramtypes", [Object, Object, Array, biometric_challenge_service_1.BiometricChallengeService,
|
|
164
|
+
auth_service_1.AuthService, Object])
|
|
111
165
|
], BiometricAuthService);
|
|
112
166
|
//# sourceMappingURL=biometric-auth.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"biometric-auth.service.js","sourceRoot":"","sources":["../../src/services/biometric-auth.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"biometric-auth.service.js","sourceRoot":"","sources":["../../src/services/biometric-auth.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BiometricChallengeRecord, IBiometricChallengeStore } from '../interfaces/biometric-repository.interface';
|
|
2
|
+
import { IRateLimiter } from '../interfaces/rate-limiter.interface';
|
|
3
|
+
import { IAuthLogger } from '../interfaces/auth-logger.interface';
|
|
4
|
+
import type { AuthModuleOptions } from '../auth.module';
|
|
5
|
+
export declare class BiometricChallengeService {
|
|
6
|
+
private readonly store;
|
|
7
|
+
private readonly rateLimiter;
|
|
8
|
+
private readonly securityLogger;
|
|
9
|
+
private readonly options;
|
|
10
|
+
private lastSweepAt;
|
|
11
|
+
private readonly ipHashSalt;
|
|
12
|
+
constructor(store: IBiometricChallengeStore, rateLimiter: IRateLimiter, securityLogger: IAuthLogger, options: AuthModuleOptions);
|
|
13
|
+
private get expirySeconds();
|
|
14
|
+
private get rateLimit();
|
|
15
|
+
issueChallenge(credentialId: string, opts?: {
|
|
16
|
+
ipAddress?: string;
|
|
17
|
+
realm?: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
challengeId: string;
|
|
20
|
+
challenge: string;
|
|
21
|
+
expiresAt: Date;
|
|
22
|
+
} | null>;
|
|
23
|
+
private withinLimit;
|
|
24
|
+
consumeChallenge(challengeId: string): Promise<BiometricChallengeRecord | null>;
|
|
25
|
+
private sweep;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=biometric-challenge.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"biometric-challenge.service.d.ts","sourceRoot":"","sources":["../../src/services/biometric-challenge.service.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,WAAW,EAAiB,MAAM,qCAAqC,CAAC;AAGjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAyBxD,qBACa,yBAAyB;IAgBlC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAE5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IArB1B,OAAO,CAAC,WAAW,CAAK;IAWxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAIjB,KAAK,EAAE,wBAAwB,EAE/B,WAAW,EAAE,YAAY,EAEzB,cAAc,EAAE,WAAW,EAE3B,OAAO,EAAE,iBAAiB;IAK7C,OAAO,KAAK,aAAa,GAExB;IAED,OAAO,KAAK,SAAS,GAEpB;IAgCK,cAAc,CAClB,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAChD,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;YAoDhE,WAAW;IAsBnB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC;YAqBvE,KAAK;CAkBpB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
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.BiometricChallengeService = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const crypto_1 = require("crypto");
|
|
18
|
+
const auth_logger_interface_1 = require("../interfaces/auth-logger.interface");
|
|
19
|
+
const constants_1 = require("../constants");
|
|
20
|
+
const ip_hash_1 = require("../utils/ip-hash");
|
|
21
|
+
const CHALLENGE_BYTES = 32;
|
|
22
|
+
const DEFAULT_EXPIRY_SECONDS = 60;
|
|
23
|
+
const DEFAULT_RATE_LIMIT = { maxAttempts: 5, windowMs: 60_000 };
|
|
24
|
+
const SWEEP_THROTTLE_MS = 2 * 60_000;
|
|
25
|
+
let BiometricChallengeService = class BiometricChallengeService {
|
|
26
|
+
constructor(store, rateLimiter, securityLogger, options) {
|
|
27
|
+
this.store = store;
|
|
28
|
+
this.rateLimiter = rateLimiter;
|
|
29
|
+
this.securityLogger = securityLogger;
|
|
30
|
+
this.options = options;
|
|
31
|
+
this.lastSweepAt = 0;
|
|
32
|
+
this.ipHashSalt = process.env.AUTH_IP_HASH_SALT || this.options.jwtSecret || '';
|
|
33
|
+
}
|
|
34
|
+
get expirySeconds() {
|
|
35
|
+
return this.options.biometric?.challengeExpirySeconds ?? DEFAULT_EXPIRY_SECONDS;
|
|
36
|
+
}
|
|
37
|
+
get rateLimit() {
|
|
38
|
+
return this.options.biometric?.challengeRateLimit ?? DEFAULT_RATE_LIMIT;
|
|
39
|
+
}
|
|
40
|
+
async issueChallenge(credentialId, opts = {}) {
|
|
41
|
+
const { ipAddress, realm } = opts;
|
|
42
|
+
const { maxAttempts, windowMs } = this.rateLimit;
|
|
43
|
+
const scope = realm ? `${realm}:` : '';
|
|
44
|
+
const credentialKey = `auth:biometricChallenge:${scope}${credentialId}`;
|
|
45
|
+
if (!(await this.withinLimit(credentialKey, maxAttempts, windowMs))) {
|
|
46
|
+
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_LOGIN_FAILURE, {
|
|
47
|
+
credentialId,
|
|
48
|
+
realm,
|
|
49
|
+
reason: 'challenge_rate_limited',
|
|
50
|
+
});
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (ipAddress) {
|
|
54
|
+
const ipKey = `auth:biometricChallengeIp:${scope}${(0, ip_hash_1.hashIp)(ipAddress, this.ipHashSalt)}`;
|
|
55
|
+
if (!(await this.withinLimit(ipKey, maxAttempts * 10, windowMs))) {
|
|
56
|
+
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_LOGIN_FAILURE, {
|
|
57
|
+
ipAddress,
|
|
58
|
+
realm,
|
|
59
|
+
reason: 'challenge_ip_rate_limited',
|
|
60
|
+
});
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const challenge = (0, crypto_1.randomBytes)(CHALLENGE_BYTES).toString('base64');
|
|
65
|
+
const expiresAt = new Date(Date.now() + this.expirySeconds * 1000);
|
|
66
|
+
const challengeId = await this.store.storeChallenge({
|
|
67
|
+
credentialId,
|
|
68
|
+
challenge,
|
|
69
|
+
expiresAt,
|
|
70
|
+
});
|
|
71
|
+
void this.sweep();
|
|
72
|
+
return { challengeId, challenge, expiresAt };
|
|
73
|
+
}
|
|
74
|
+
async withinLimit(key, limit, windowMs) {
|
|
75
|
+
const { allowed } = await this.rateLimiter.checkRateLimit(key, limit, windowMs);
|
|
76
|
+
if (!allowed) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
await this.rateLimiter.recordAttempt(key, windowMs);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
async consumeChallenge(challengeId) {
|
|
83
|
+
const record = await this.store.consumeChallenge(challengeId);
|
|
84
|
+
if (!record) {
|
|
85
|
+
this.securityLogger.log(auth_logger_interface_1.SecurityEvent.BIOMETRIC_LOGIN_FAILURE, {
|
|
86
|
+
challengeId,
|
|
87
|
+
reason: 'challenge_unavailable',
|
|
88
|
+
});
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
return record;
|
|
92
|
+
}
|
|
93
|
+
async sweep() {
|
|
94
|
+
const now = Date.now();
|
|
95
|
+
if (now - this.lastSweepAt < SWEEP_THROTTLE_MS) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
this.lastSweepAt = now;
|
|
99
|
+
try {
|
|
100
|
+
await this.store.deleteExpiredChallenges();
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
this.securityLogger.warn(`Sweeping expired biometric challenges failed: ${error instanceof Error ? error.message : String(error)}. Challenges still expire — consumeChallenge re-checks it.`, 'BiometricChallengeService');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
exports.BiometricChallengeService = BiometricChallengeService;
|
|
108
|
+
exports.BiometricChallengeService = BiometricChallengeService = __decorate([
|
|
109
|
+
(0, common_1.Injectable)(),
|
|
110
|
+
__param(0, (0, common_1.Inject)(constants_1.BIOMETRIC_REPOSITORY)),
|
|
111
|
+
__param(1, (0, common_1.Inject)(constants_1.RATE_LIMITER)),
|
|
112
|
+
__param(2, (0, common_1.Inject)(constants_1.AUTH_LOGGER)),
|
|
113
|
+
__param(3, (0, common_1.Inject)(constants_1.AUTH_MODULE_OPTIONS)),
|
|
114
|
+
__metadata("design:paramtypes", [Object, Object, Object, Object])
|
|
115
|
+
], BiometricChallengeService);
|
|
116
|
+
//# sourceMappingURL=biometric-challenge.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"biometric-challenge.service.js","sourceRoot":"","sources":["../../src/services/biometric-challenge.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"biometric-verification.service.d.ts","sourceRoot":"","sources":["../../src/services/biometric-verification.service.ts"],"names":[],"mappings":"AA6BA,qBACa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiD;IACxE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAa;IAiB3C,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IA4Cb,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2C/D,OAAO,CAAC,cAAc;
|
|
1
|
+
{"version":3,"file":"biometric-verification.service.d.ts","sourceRoot":"","sources":["../../src/services/biometric-verification.service.ts"],"names":[],"mappings":"AA6BA,qBACa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiD;IACxE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAa;IAiB3C,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC;IA4Cb,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2C/D,OAAO,CAAC,cAAc;IA6DtB,sBAAsB,IAAI,MAAM,EAAE;CAGnC"}
|
|
@@ -61,6 +61,10 @@ let BiometricVerificationService = BiometricVerificationService_1 = class Biomet
|
|
|
61
61
|
if (publicKey.asymmetricKeyType !== 'ec') {
|
|
62
62
|
throw new Error(`Invalid key type: expected 'ec', got '${publicKey.asymmetricKeyType}'`);
|
|
63
63
|
}
|
|
64
|
+
const namedCurve = publicKey.asymmetricKeyDetails?.namedCurve;
|
|
65
|
+
if (namedCurve !== 'prime256v1') {
|
|
66
|
+
throw new Error(`Invalid curve: expected 'prime256v1' (P-256), got '${namedCurve ?? 'unknown'}'`);
|
|
67
|
+
}
|
|
64
68
|
return publicKey;
|
|
65
69
|
}
|
|
66
70
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"biometric-verification.service.js","sourceRoot":"","sources":["../../src/services/biometric-verification.service.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAyE;AACzE,mCAAkE;AA6B3D,IAAM,4BAA4B,oCAAlC,MAAM,4BAA4B;IAAlC;QACY,WAAM,GAAG,IAAI,eAAM,CAAC,8BAA4B,CAAC,IAAI,CAAC,CAAC;QACvD,wBAAmB,GAAG,CAAC,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"biometric-verification.service.js","sourceRoot":"","sources":["../../src/services/biometric-verification.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-repositories.d.ts","sourceRoot":"","sources":["../../src/test-utils/mock-repositories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAM/I,wBAAgB,wBAAwB,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAwCvE;AAKD,wBAAgB,gCAAgC,IAAI,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAYvF;AAKD,wBAAgB,gCAAgC,IAAI,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAOvF;AAKD,wBAAgB,8BAA8B,IAAI,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CASnF;AAKD,wBAAgB,6BAA6B,IAAI,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"mock-repositories.d.ts","sourceRoot":"","sources":["../../src/test-utils/mock-repositories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAM/I,wBAAgB,wBAAwB,IAAI,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAwCvE;AAKD,wBAAgB,gCAAgC,IAAI,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAYvF;AAKD,wBAAgB,gCAAgC,IAAI,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAOvF;AAKD,wBAAgB,8BAA8B,IAAI,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CASnF;AAKD,wBAAgB,6BAA6B,IAAI,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAWjF"}
|
|
@@ -78,13 +78,14 @@ function createMockBruteForceRepository() {
|
|
|
78
78
|
}
|
|
79
79
|
function createMockBiometricRepository() {
|
|
80
80
|
return {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
storeCredential: jest.fn(),
|
|
82
|
+
getCredential: jest.fn(),
|
|
83
|
+
listCredentials: jest.fn(),
|
|
84
|
+
deactivateCredential: jest.fn(),
|
|
85
|
+
touchCredentialLastUsed: jest.fn(),
|
|
86
|
+
storeChallenge: jest.fn(),
|
|
87
|
+
consumeChallenge: jest.fn(),
|
|
88
|
+
deleteExpiredChallenges: jest.fn(),
|
|
88
89
|
};
|
|
89
90
|
}
|
|
90
91
|
//# sourceMappingURL=mock-repositories.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-repositories.js","sourceRoot":"","sources":["../../src/test-utils/mock-repositories.ts"],"names":[],"mappings":";;AAMA,4DAwCC;AAKD,4EAYC;AAKD,4EAOC;AAKD,wEASC;AAKD,
|
|
1
|
+
{"version":3,"file":"mock-repositories.js","sourceRoot":"","sources":["../../src/test-utils/mock-repositories.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IBiometricVerifier } from '../interfaces/biometric-verifier.interface';
|
|
2
|
+
import { BiometricVerificationService } from '../services/biometric-verification.service';
|
|
3
|
+
export declare class Es256DeviceKeyVerifier implements IBiometricVerifier {
|
|
4
|
+
private readonly verification;
|
|
5
|
+
readonly algorithm = "ES256";
|
|
6
|
+
constructor(verification?: BiometricVerificationService);
|
|
7
|
+
verify(input: {
|
|
8
|
+
publicKey: string;
|
|
9
|
+
challenge: string;
|
|
10
|
+
signature: string;
|
|
11
|
+
}): Promise<boolean>;
|
|
12
|
+
validatePublicKey(publicKey: string): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=es256-device-key.verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"es256-device-key.verifier.d.ts","sourceRoot":"","sources":["../../src/verifiers/es256-device-key.verifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,MAAM,4CAA4C,CAAC;AAwB1F,qBACa,sBAAuB,YAAW,kBAAkB;IAI7D,OAAO,CAAC,QAAQ,CAAC,YAAY;IAH/B,QAAQ,CAAC,SAAS,WAAW;gBAGV,YAAY,GAAE,4BAAiE;IAG5F,MAAM,CAAC,KAAK,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBd,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAO7D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.Es256DeviceKeyVerifier = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const biometric_verification_service_1 = require("../services/biometric-verification.service");
|
|
15
|
+
let Es256DeviceKeyVerifier = class Es256DeviceKeyVerifier {
|
|
16
|
+
constructor(verification = new biometric_verification_service_1.BiometricVerificationService()) {
|
|
17
|
+
this.verification = verification;
|
|
18
|
+
this.algorithm = 'ES256';
|
|
19
|
+
}
|
|
20
|
+
async verify(input) {
|
|
21
|
+
try {
|
|
22
|
+
return await this.verification.verifySignature(input.publicKey, input.challenge, input.signature);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async validatePublicKey(publicKey) {
|
|
29
|
+
try {
|
|
30
|
+
return await this.verification.validatePublicKey(publicKey);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.Es256DeviceKeyVerifier = Es256DeviceKeyVerifier;
|
|
38
|
+
exports.Es256DeviceKeyVerifier = Es256DeviceKeyVerifier = __decorate([
|
|
39
|
+
(0, common_1.Injectable)(),
|
|
40
|
+
__metadata("design:paramtypes", [biometric_verification_service_1.BiometricVerificationService])
|
|
41
|
+
], Es256DeviceKeyVerifier);
|
|
42
|
+
//# sourceMappingURL=es256-device-key.verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"es256-device-key.verifier.js","sourceRoot":"","sources":["../../src/verifiers/es256-device-key.verifier.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAE5C,+FAA0F;AAyBnF,IAAM,sBAAsB,GAA5B,MAAM,sBAAsB;IAGjC,YACmB,eAA6C,IAAI,6DAA4B,EAAE;QAA/E,iBAAY,GAAZ,YAAY,CAAmE;QAHzF,cAAS,GAAG,OAAO,CAAC;IAI1B,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,KAIZ;QACC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAC5C,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,SAAS,CAChB,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YAMP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,SAAiB;QACvC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF,CAAA;AAnCY,wDAAsB;iCAAtB,sBAAsB;IADlC,IAAA,mBAAU,GAAE;qCAKsB,6DAA4B;GAJlD,sBAAsB,CAmClC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ambushsoftworks/nestjs-auth-graphql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Production-grade authentication package for NestJS with GraphQL, supporting JWT, OAuth, email/SMS verification, and biometric auth",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"lint": "eslint \"{src,test}/**/*.ts\"",
|
|
24
24
|
"format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
|
|
25
25
|
"prepublishOnly": "npm run build",
|
|
26
|
-
"lint:fix": "eslint \"{src,test}/**/*.ts\" --fix"
|
|
26
|
+
"lint:fix": "eslint \"{src,test}/**/*.ts\" --fix",
|
|
27
|
+
"release": "node scripts/release.js",
|
|
28
|
+
"release:verify": "node scripts/verify-release.js"
|
|
27
29
|
},
|
|
28
30
|
"keywords": [
|
|
29
31
|
"nestjs",
|
|
@@ -46,6 +48,10 @@
|
|
|
46
48
|
"type": "git",
|
|
47
49
|
"url": "https://gitlab.com/ambushworks/nestjs-auth-graphql.git"
|
|
48
50
|
},
|
|
51
|
+
"homepage": "https://gitlab.com/ambushworks/nestjs-auth-graphql#readme",
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://gitlab.com/ambushworks/nestjs-auth-graphql/-/issues"
|
|
54
|
+
},
|
|
49
55
|
"peerDependencies": {
|
|
50
56
|
"@nestjs/common": "^10.0.0 || ^11.0.0",
|
|
51
57
|
"@nestjs/core": "^10.0.0 || ^11.0.0",
|
|
@@ -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
|