@nauth-toolkit/core 0.1.0 → 0.1.5
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 +9 -0
- package/package.json +8 -3
- package/jest.config.js +0 -15
- package/jest.setup.ts +0 -6
- package/src/adapters/database-columns.ts +0 -165
- package/src/adapters/express.adapter.ts +0 -385
- package/src/adapters/fastify.adapter.ts +0 -416
- package/src/adapters/index.ts +0 -16
- package/src/adapters/storage.factory.ts +0 -143
- package/src/bootstrap.ts +0 -374
- package/src/dto/auth-challenge.dto.ts +0 -231
- package/src/dto/auth-response.dto.ts +0 -253
- package/src/dto/challenge-response.dto.ts +0 -234
- package/src/dto/change-password-request.dto.ts +0 -50
- package/src/dto/change-password-response.dto.ts +0 -29
- package/src/dto/change-password.dto.ts +0 -57
- package/src/dto/error-response.dto.ts +0 -136
- package/src/dto/get-available-methods.dto.ts +0 -55
- package/src/dto/get-challenge-data-response.dto.ts +0 -28
- package/src/dto/get-challenge-data.dto.ts +0 -69
- package/src/dto/get-client-info.dto.ts +0 -104
- package/src/dto/get-device-token-response.dto.ts +0 -25
- package/src/dto/get-events-by-type.dto.ts +0 -76
- package/src/dto/get-ip-address-response.dto.ts +0 -24
- package/src/dto/get-mfa-status.dto.ts +0 -94
- package/src/dto/get-risk-assessment-history.dto.ts +0 -39
- package/src/dto/get-session-id-response.dto.ts +0 -25
- package/src/dto/get-setup-data-response.dto.ts +0 -31
- package/src/dto/get-setup-data.dto.ts +0 -75
- package/src/dto/get-suspicious-activity.dto.ts +0 -42
- package/src/dto/get-user-agent-response.dto.ts +0 -23
- package/src/dto/get-user-auth-history.dto.ts +0 -95
- package/src/dto/get-user-by-email.dto.ts +0 -61
- package/src/dto/get-user-by-id.dto.ts +0 -46
- package/src/dto/get-user-devices.dto.ts +0 -53
- package/src/dto/get-user-response.dto.ts +0 -17
- package/src/dto/has-provider.dto.ts +0 -56
- package/src/dto/index.ts +0 -57
- package/src/dto/is-trusted-device-response.dto.ts +0 -34
- package/src/dto/list-providers-response.dto.ts +0 -23
- package/src/dto/login.dto.ts +0 -95
- package/src/dto/logout-all-response.dto.ts +0 -24
- package/src/dto/logout-all.dto.ts +0 -65
- package/src/dto/logout-response.dto.ts +0 -25
- package/src/dto/logout.dto.ts +0 -64
- package/src/dto/refresh-token.dto.ts +0 -36
- package/src/dto/remove-devices.dto.ts +0 -85
- package/src/dto/resend-code-response.dto.ts +0 -32
- package/src/dto/resend-code.dto.ts +0 -51
- package/src/dto/reset-password.dto.ts +0 -115
- package/src/dto/respond-challenge.dto.ts +0 -272
- package/src/dto/set-mfa-exemption.dto.ts +0 -112
- package/src/dto/set-must-change-password-response.dto.ts +0 -27
- package/src/dto/set-must-change-password.dto.ts +0 -46
- package/src/dto/set-preferred-method.dto.ts +0 -80
- package/src/dto/setup-mfa.dto.ts +0 -98
- package/src/dto/signup.dto.ts +0 -174
- package/src/dto/social-auth.dto.ts +0 -422
- package/src/dto/trust-device-response.dto.ts +0 -30
- package/src/dto/trust-device.dto.ts +0 -9
- package/src/dto/update-user-attributes-request.dto.ts +0 -51
- package/src/dto/user-response.dto.ts +0 -138
- package/src/dto/user-update.dto.ts +0 -222
- package/src/dto/verify-email.dto.ts +0 -313
- package/src/dto/verify-mfa-code.dto.ts +0 -103
- package/src/dto/verify-phone-by-sub.dto.ts +0 -78
- package/src/dto/verify-phone.dto.ts +0 -245
- package/src/entities/auth-audit.entity.ts +0 -232
- package/src/entities/challenge-session.entity.ts +0 -116
- package/src/entities/index.ts +0 -29
- package/src/entities/login-attempt.entity.ts +0 -64
- package/src/entities/mfa-device.entity.ts +0 -151
- package/src/entities/rate-limit.entity.ts +0 -44
- package/src/entities/session.entity.ts +0 -180
- package/src/entities/social-account.entity.ts +0 -96
- package/src/entities/storage-lock.entity.ts +0 -39
- package/src/entities/trusted-device.entity.ts +0 -112
- package/src/entities/user.entity.ts +0 -243
- package/src/entities/verification-token.entity.ts +0 -141
- package/src/enums/auth-audit-event-type.enum.ts +0 -360
- package/src/enums/error-codes.enum.ts +0 -420
- package/src/enums/mfa-method.enum.ts +0 -97
- package/src/enums/risk-factor.enum.ts +0 -111
- package/src/exceptions/nauth.exception.ts +0 -231
- package/src/handlers/auth.handler.ts +0 -260
- package/src/handlers/client-info.handler.ts +0 -101
- package/src/handlers/csrf.handler.ts +0 -156
- package/src/handlers/token-delivery.handler.ts +0 -118
- package/src/index.ts +0 -118
- package/src/interfaces/client-info.interface.ts +0 -85
- package/src/interfaces/config.interface.ts +0 -2135
- package/src/interfaces/entities.interface.ts +0 -226
- package/src/interfaces/index.ts +0 -15
- package/src/interfaces/logger.interface.ts +0 -283
- package/src/interfaces/mfa-provider.interface.ts +0 -154
- package/src/interfaces/oauth.interface.ts +0 -148
- package/src/interfaces/provider.interface.ts +0 -47
- package/src/interfaces/social-auth-provider.interface.ts +0 -131
- package/src/interfaces/storage-adapter.interface.ts +0 -82
- package/src/interfaces/template.interface.ts +0 -510
- package/src/interfaces/token-verifier.interface.ts +0 -110
- package/src/internal.ts +0 -178
- package/src/platform/interfaces.ts +0 -299
- package/src/schemas/auth-config.schema.ts +0 -646
- package/src/services/adaptive-mfa-decision.service.spec.ts +0 -1058
- package/src/services/adaptive-mfa-decision.service.ts +0 -457
- package/src/services/auth-audit.service.spec.ts +0 -675
- package/src/services/auth-audit.service.ts +0 -558
- package/src/services/auth-challenge-helper.service.spec.ts +0 -3227
- package/src/services/auth-challenge-helper.service.ts +0 -825
- package/src/services/auth-flow-context-builder.service.ts +0 -520
- package/src/services/auth-flow-rules.ts +0 -202
- package/src/services/auth-flow-state-definitions.ts +0 -190
- package/src/services/auth-flow-state-machine.service.ts +0 -207
- package/src/services/auth-flow-state-machine.types.ts +0 -316
- package/src/services/auth.service.spec.ts +0 -4195
- package/src/services/auth.service.ts +0 -3727
- package/src/services/challenge.service.spec.ts +0 -1363
- package/src/services/challenge.service.ts +0 -696
- package/src/services/client-info.service.spec.ts +0 -572
- package/src/services/client-info.service.ts +0 -374
- package/src/services/csrf.service.ts +0 -54
- package/src/services/email-verification.service.spec.ts +0 -1229
- package/src/services/email-verification.service.ts +0 -578
- package/src/services/geo-location.service.spec.ts +0 -603
- package/src/services/geo-location.service.ts +0 -599
- package/src/services/index.ts +0 -13
- package/src/services/jwt.service.spec.ts +0 -882
- package/src/services/jwt.service.ts +0 -621
- package/src/services/mfa-base.service.spec.ts +0 -246
- package/src/services/mfa-base.service.ts +0 -611
- package/src/services/mfa.service.spec.ts +0 -693
- package/src/services/mfa.service.ts +0 -960
- package/src/services/password.service.spec.ts +0 -166
- package/src/services/password.service.ts +0 -309
- package/src/services/phone-verification.service.spec.ts +0 -1120
- package/src/services/phone-verification.service.ts +0 -751
- package/src/services/risk-detection.service.spec.ts +0 -1292
- package/src/services/risk-detection.service.ts +0 -1012
- package/src/services/risk-scoring.service.spec.ts +0 -204
- package/src/services/risk-scoring.service.ts +0 -131
- package/src/services/session.service.spec.ts +0 -1293
- package/src/services/session.service.ts +0 -803
- package/src/services/social-account.service.spec.ts +0 -725
- package/src/services/social-auth-base.service.spec.ts +0 -418
- package/src/services/social-auth-base.service.ts +0 -581
- package/src/services/social-auth.service.spec.ts +0 -238
- package/src/services/social-auth.service.ts +0 -436
- package/src/services/social-provider-registry.service.spec.ts +0 -238
- package/src/services/social-provider-registry.service.ts +0 -122
- package/src/services/trusted-device.service.spec.ts +0 -505
- package/src/services/trusted-device.service.ts +0 -339
- package/src/storage/account-lockout-storage.service.spec.ts +0 -310
- package/src/storage/account-lockout-storage.service.ts +0 -89
- package/src/storage/index.ts +0 -3
- package/src/storage/memory-storage.adapter.ts +0 -443
- package/src/storage/rate-limit-storage.service.spec.ts +0 -247
- package/src/storage/rate-limit-storage.service.ts +0 -38
- package/src/templates/html-template.engine.spec.ts +0 -161
- package/src/templates/html-template.engine.ts +0 -688
- package/src/templates/index.ts +0 -7
- package/src/utils/common-passwords.spec.ts +0 -230
- package/src/utils/common-passwords.ts +0 -170
- package/src/utils/context-storage.ts +0 -188
- package/src/utils/cookie-names.util.ts +0 -67
- package/src/utils/cookies.util.ts +0 -94
- package/src/utils/index.ts +0 -12
- package/src/utils/ip-extractor.spec.ts +0 -330
- package/src/utils/ip-extractor.ts +0 -220
- package/src/utils/nauth-logger.spec.ts +0 -388
- package/src/utils/nauth-logger.ts +0 -215
- package/src/utils/pii-redactor.spec.ts +0 -130
- package/src/utils/pii-redactor.ts +0 -288
- package/src/utils/setup/get-repositories.ts +0 -140
- package/src/utils/setup/init-services.ts +0 -422
- package/src/utils/setup/init-social.ts +0 -189
- package/src/utils/setup/init-storage.ts +0 -94
- package/src/utils/setup/register-mfa.ts +0 -165
- package/src/utils/setup/run-nauth-migrations.ts +0 -61
- package/src/utils/token-delivery-policy.ts +0 -38
- package/src/validators/template.validator.ts +0 -219
- package/tsconfig.json +0 -37
- package/tsconfig.lint.json +0 -6
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { Repository } from 'typeorm';
|
|
2
|
-
import { BaseMFAProviderService } from './mfa-base.service';
|
|
3
|
-
import { BaseMFADevice, BaseUser } from '../entities';
|
|
4
|
-
import { IUser } from '../interfaces/entities.interface';
|
|
5
|
-
import { NAuthConfig } from '../interfaces/config.interface';
|
|
6
|
-
import { NAuthLogger } from '../utils/nauth-logger';
|
|
7
|
-
import { NAuthException } from '../exceptions/nauth.exception';
|
|
8
|
-
import { AuthErrorCode } from '../enums/error-codes.enum';
|
|
9
|
-
import { MFAMethod } from '../enums/mfa-method.enum';
|
|
10
|
-
import { ChallengeService } from './challenge.service';
|
|
11
|
-
import { AuthAuditService } from './auth-audit.service';
|
|
12
|
-
import { ClientInfoService } from './client-info.service';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Test implementation of BaseMFAProviderService
|
|
16
|
-
*/
|
|
17
|
-
class TestMFAProviderService extends BaseMFAProviderService {
|
|
18
|
-
readonly methodName = 'test';
|
|
19
|
-
|
|
20
|
-
async setup(user: IUser, _setupData?: unknown): Promise<unknown> {
|
|
21
|
-
return { test: 'setup' };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async verifySetup(user: IUser, verificationData: unknown, deviceName?: string): Promise<number> {
|
|
25
|
-
return 1;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async verify(user: IUser, code: unknown, deviceId?: number): Promise<boolean> {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Base MFA Provider Service Unit Tests
|
|
35
|
-
*
|
|
36
|
-
* Tests shared functionality in BaseMFAProviderService including device management,
|
|
37
|
-
* backup codes, and helper methods. Uses direct instantiation, no NestJS dependencies.
|
|
38
|
-
*/
|
|
39
|
-
describe('BaseMFAProviderService', () => {
|
|
40
|
-
let service: TestMFAProviderService;
|
|
41
|
-
let mockMfaDeviceRepository: jest.Mocked<Repository<BaseMFADevice>>;
|
|
42
|
-
let mockUserRepository: jest.Mocked<Repository<BaseUser>>;
|
|
43
|
-
let mockConfig: NAuthConfig;
|
|
44
|
-
let mockLogger: NAuthLogger;
|
|
45
|
-
let mockPasswordService: unknown;
|
|
46
|
-
let mockChallengeService: jest.Mocked<ChallengeService>;
|
|
47
|
-
let mockAuditService: jest.Mocked<AuthAuditService>;
|
|
48
|
-
let mockClientInfoService: jest.Mocked<ClientInfoService>;
|
|
49
|
-
let mockUser: IUser;
|
|
50
|
-
|
|
51
|
-
beforeEach(() => {
|
|
52
|
-
mockMfaDeviceRepository = {
|
|
53
|
-
create: jest.fn(),
|
|
54
|
-
save: jest.fn(),
|
|
55
|
-
find: jest.fn(),
|
|
56
|
-
findOne: jest.fn(),
|
|
57
|
-
} as any;
|
|
58
|
-
|
|
59
|
-
mockUserRepository = {
|
|
60
|
-
save: jest.fn(),
|
|
61
|
-
findOne: jest.fn(),
|
|
62
|
-
} as any;
|
|
63
|
-
|
|
64
|
-
mockLogger = {
|
|
65
|
-
log: jest.fn(),
|
|
66
|
-
error: jest.fn(),
|
|
67
|
-
warn: jest.fn(),
|
|
68
|
-
debug: jest.fn(),
|
|
69
|
-
} as any;
|
|
70
|
-
|
|
71
|
-
mockConfig = {
|
|
72
|
-
mfa: {
|
|
73
|
-
enabled: true,
|
|
74
|
-
allowedMethods: [MFAMethod.TOTP as any],
|
|
75
|
-
},
|
|
76
|
-
} as NAuthConfig;
|
|
77
|
-
|
|
78
|
-
mockPasswordService = {
|
|
79
|
-
hashPassword: jest.fn().mockResolvedValue('hashed-password'),
|
|
80
|
-
verifyPassword: jest.fn().mockResolvedValue(true),
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
mockChallengeService = {
|
|
84
|
-
deleteUserChallengeSessions: jest.fn(),
|
|
85
|
-
} as any;
|
|
86
|
-
|
|
87
|
-
mockAuditService = {
|
|
88
|
-
recordEvent: jest.fn(),
|
|
89
|
-
} as any;
|
|
90
|
-
|
|
91
|
-
mockClientInfoService = {
|
|
92
|
-
getClientInfo: jest.fn().mockResolvedValue({
|
|
93
|
-
ipAddress: '192.168.1.1',
|
|
94
|
-
userAgent: 'test-agent',
|
|
95
|
-
}),
|
|
96
|
-
} as any;
|
|
97
|
-
|
|
98
|
-
mockUser = {
|
|
99
|
-
id: 1,
|
|
100
|
-
sub: 'user-123',
|
|
101
|
-
email: 'user@example.com',
|
|
102
|
-
mfaEnabled: false,
|
|
103
|
-
} as IUser;
|
|
104
|
-
|
|
105
|
-
service = new TestMFAProviderService(
|
|
106
|
-
mockMfaDeviceRepository,
|
|
107
|
-
mockUserRepository,
|
|
108
|
-
mockConfig,
|
|
109
|
-
mockLogger,
|
|
110
|
-
mockPasswordService,
|
|
111
|
-
mockChallengeService,
|
|
112
|
-
mockAuditService,
|
|
113
|
-
mockClientInfoService,
|
|
114
|
-
);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
afterEach(() => {
|
|
118
|
-
jest.clearAllMocks();
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('isMethodAllowed', () => {
|
|
122
|
-
it('should return true when method is in allowed methods', () => {
|
|
123
|
-
mockConfig.mfa!.allowedMethods = ['test' as any];
|
|
124
|
-
expect(service.isMethodAllowed()).toBe(true);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should return false when method is not in allowed methods', () => {
|
|
128
|
-
mockConfig.mfa!.allowedMethods = [MFAMethod.TOTP as any];
|
|
129
|
-
expect(service.isMethodAllowed()).toBe(false);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe('generateBackupCodes', () => {
|
|
134
|
-
it('should generate backup codes', async () => {
|
|
135
|
-
const codes = await service.generateBackupCodes(mockUser);
|
|
136
|
-
|
|
137
|
-
expect(codes.length).toBe(10);
|
|
138
|
-
expect(codes[0]).toMatch(/^[A-Z0-9]+$/);
|
|
139
|
-
expect(mockUserRepository.save).toHaveBeenCalled();
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should use custom code count from config', async () => {
|
|
143
|
-
mockConfig.mfa!.backup = { codeCount: 5, codeLength: 8 };
|
|
144
|
-
const codes = await service.generateBackupCodes(mockUser);
|
|
145
|
-
|
|
146
|
-
expect(codes.length).toBe(5);
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('should throw error when password service is not available', async () => {
|
|
150
|
-
const serviceWithoutPassword = new TestMFAProviderService(
|
|
151
|
-
mockMfaDeviceRepository,
|
|
152
|
-
mockUserRepository,
|
|
153
|
-
mockConfig,
|
|
154
|
-
mockLogger,
|
|
155
|
-
undefined,
|
|
156
|
-
mockChallengeService,
|
|
157
|
-
mockAuditService,
|
|
158
|
-
mockClientInfoService,
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
await serviceWithoutPassword.generateBackupCodes(mockUser);
|
|
163
|
-
fail('Should have thrown NAuthException');
|
|
164
|
-
} catch (error) {
|
|
165
|
-
expect(error).toBeInstanceOf(NAuthException);
|
|
166
|
-
expect((error as NAuthException).code).toBe(AuthErrorCode.VALIDATION_FAILED);
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
describe('verifyBackupCode', () => {
|
|
172
|
-
it('should verify and remove backup code', async () => {
|
|
173
|
-
const userWithCodes = {
|
|
174
|
-
...mockUser,
|
|
175
|
-
backupCodes: ['hashed-code-1', 'hashed-code-2'],
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
(mockPasswordService as any).verifyPassword.mockResolvedValueOnce(true);
|
|
179
|
-
|
|
180
|
-
const result = await (service as any).verifyBackupCode(userWithCodes, 'code-1');
|
|
181
|
-
|
|
182
|
-
expect(result).toBe(true);
|
|
183
|
-
expect(mockUserRepository.save).toHaveBeenCalled();
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
it('should return false when no backup codes available', async () => {
|
|
187
|
-
const result = await (service as any).verifyBackupCode(mockUser, 'code');
|
|
188
|
-
|
|
189
|
-
expect(result).toBe(false);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('should return false when code is invalid', async () => {
|
|
193
|
-
const userWithCodes = {
|
|
194
|
-
...mockUser,
|
|
195
|
-
backupCodes: ['hashed-code-1'],
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
(mockPasswordService as any).verifyPassword.mockResolvedValue(false);
|
|
199
|
-
|
|
200
|
-
const result = await (service as any).verifyBackupCode(userWithCodes, 'invalid-code');
|
|
201
|
-
|
|
202
|
-
expect(result).toBe(false);
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe('generateRandomCode', () => {
|
|
207
|
-
it('should generate random code of specified length', () => {
|
|
208
|
-
const code = (service as any).generateRandomCode(8);
|
|
209
|
-
|
|
210
|
-
expect(code.length).toBe(8);
|
|
211
|
-
expect(code).toMatch(/^[A-Z0-9]+$/);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
describe('maskPhone', () => {
|
|
216
|
-
it('should mask phone number', () => {
|
|
217
|
-
const masked = (service as any).maskPhone('+1234567890');
|
|
218
|
-
expect(masked).toBe('***-***-7890');
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it('should return original phone if too short', () => {
|
|
222
|
-
const masked = (service as any).maskPhone('123');
|
|
223
|
-
expect(masked).toBe('123');
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
describe('isMFARequired', () => {
|
|
228
|
-
it('should return false when user is MFA exempt', async () => {
|
|
229
|
-
const exemptUser = { ...mockUser, mfaExempt: true };
|
|
230
|
-
const result = await (service as any).isMFARequired(exemptUser);
|
|
231
|
-
expect(result).toBe(false);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('should return false when MFA is not enabled', async () => {
|
|
235
|
-
mockConfig.mfa!.enabled = false;
|
|
236
|
-
const result = await (service as any).isMFARequired(mockUser);
|
|
237
|
-
expect(result).toBe(false);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
it('should return false when enforcement is OPTIONAL', async () => {
|
|
241
|
-
mockConfig.mfa!.enforcement = 'OPTIONAL';
|
|
242
|
-
const result = await (service as any).isMFARequired(mockUser);
|
|
243
|
-
expect(result).toBe(false);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
});
|