@aranzatech/aranza-auth 0.1.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 +40 -0
- package/README.md +468 -0
- package/dist/auth-repository.interface-BMlJc-98.d.cts +90 -0
- package/dist/auth-repository.interface-BMlJc-98.d.ts +90 -0
- package/dist/chunk-DKYNHXY2.js +36 -0
- package/dist/chunk-DKYNHXY2.js.map +1 -0
- package/dist/index.cjs +681 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +127 -0
- package/dist/index.d.ts +127 -0
- package/dist/index.js +618 -0
- package/dist/index.js.map +1 -0
- package/dist/mongo/index.cjs +256 -0
- package/dist/mongo/index.cjs.map +1 -0
- package/dist/mongo/index.d.cts +65 -0
- package/dist/mongo/index.d.ts +65 -0
- package/dist/mongo/index.js +226 -0
- package/dist/mongo/index.js.map +1 -0
- package/package.json +102 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var common = require('@nestjs/common');
|
|
4
|
+
var jwt = require('@nestjs/jwt');
|
|
5
|
+
var passport = require('@nestjs/passport');
|
|
6
|
+
var bcrypt = require('bcryptjs');
|
|
7
|
+
var crypto = require('crypto');
|
|
8
|
+
var passportJwt = require('passport-jwt');
|
|
9
|
+
var classValidator = require('class-validator');
|
|
10
|
+
|
|
11
|
+
function _interopNamespace(e) {
|
|
12
|
+
if (e && e.__esModule) return e;
|
|
13
|
+
var n = Object.create(null);
|
|
14
|
+
if (e) {
|
|
15
|
+
Object.keys(e).forEach(function (k) {
|
|
16
|
+
if (k !== 'default') {
|
|
17
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () { return e[k]; }
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
n.default = e;
|
|
26
|
+
return Object.freeze(n);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var bcrypt__namespace = /*#__PURE__*/_interopNamespace(bcrypt);
|
|
30
|
+
|
|
31
|
+
var __defProp = Object.defineProperty;
|
|
32
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
33
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
34
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
35
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
36
|
+
if (decorator = decorators[i])
|
|
37
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
38
|
+
if (kind && result) __defProp(target, key, result);
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
42
|
+
var CurrentUser = common.createParamDecorator(
|
|
43
|
+
(_data, ctx) => {
|
|
44
|
+
const request = ctx.switchToHttp().getRequest();
|
|
45
|
+
return request.user;
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
exports.JwtAuthGuard = class JwtAuthGuard extends passport.AuthGuard("jwt") {
|
|
49
|
+
};
|
|
50
|
+
exports.JwtAuthGuard = __decorateClass([
|
|
51
|
+
common.Injectable()
|
|
52
|
+
], exports.JwtAuthGuard);
|
|
53
|
+
|
|
54
|
+
// src/controllers/auth.controller.ts
|
|
55
|
+
var AuthController = class {
|
|
56
|
+
constructor(authService) {
|
|
57
|
+
this.authService = authService;
|
|
58
|
+
}
|
|
59
|
+
register(dto) {
|
|
60
|
+
return this.authService.register(dto);
|
|
61
|
+
}
|
|
62
|
+
login(dto) {
|
|
63
|
+
return this.authService.login(dto);
|
|
64
|
+
}
|
|
65
|
+
refresh(dto) {
|
|
66
|
+
return this.authService.refresh(dto.refreshToken);
|
|
67
|
+
}
|
|
68
|
+
logout(user) {
|
|
69
|
+
return this.authService.logout(user.sub);
|
|
70
|
+
}
|
|
71
|
+
me(user) {
|
|
72
|
+
return this.authService.me(user.sub);
|
|
73
|
+
}
|
|
74
|
+
verifyEmail(dto) {
|
|
75
|
+
return this.authService.verifyEmail(dto.token);
|
|
76
|
+
}
|
|
77
|
+
forgotPassword(dto) {
|
|
78
|
+
return this.authService.forgotPassword(dto.email);
|
|
79
|
+
}
|
|
80
|
+
resetPassword(dto) {
|
|
81
|
+
return this.authService.resetPassword(dto.token, dto.newPassword);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
__decorateClass([
|
|
85
|
+
common.Post("register"),
|
|
86
|
+
__decorateParam(0, common.Body())
|
|
87
|
+
], AuthController.prototype, "register", 1);
|
|
88
|
+
__decorateClass([
|
|
89
|
+
common.Post("login"),
|
|
90
|
+
__decorateParam(0, common.Body())
|
|
91
|
+
], AuthController.prototype, "login", 1);
|
|
92
|
+
__decorateClass([
|
|
93
|
+
common.Post("refresh"),
|
|
94
|
+
common.HttpCode(common.HttpStatus.OK),
|
|
95
|
+
__decorateParam(0, common.Body())
|
|
96
|
+
], AuthController.prototype, "refresh", 1);
|
|
97
|
+
__decorateClass([
|
|
98
|
+
common.Post("logout"),
|
|
99
|
+
common.UseGuards(exports.JwtAuthGuard),
|
|
100
|
+
common.HttpCode(common.HttpStatus.OK),
|
|
101
|
+
__decorateParam(0, CurrentUser())
|
|
102
|
+
], AuthController.prototype, "logout", 1);
|
|
103
|
+
__decorateClass([
|
|
104
|
+
common.Get("me"),
|
|
105
|
+
common.UseGuards(exports.JwtAuthGuard),
|
|
106
|
+
__decorateParam(0, CurrentUser())
|
|
107
|
+
], AuthController.prototype, "me", 1);
|
|
108
|
+
__decorateClass([
|
|
109
|
+
common.Post("verify-email"),
|
|
110
|
+
common.HttpCode(common.HttpStatus.OK),
|
|
111
|
+
__decorateParam(0, common.Body())
|
|
112
|
+
], AuthController.prototype, "verifyEmail", 1);
|
|
113
|
+
__decorateClass([
|
|
114
|
+
common.Post("forgot-password"),
|
|
115
|
+
common.HttpCode(common.HttpStatus.OK),
|
|
116
|
+
__decorateParam(0, common.Body())
|
|
117
|
+
], AuthController.prototype, "forgotPassword", 1);
|
|
118
|
+
__decorateClass([
|
|
119
|
+
common.Post("reset-password"),
|
|
120
|
+
common.HttpCode(common.HttpStatus.OK),
|
|
121
|
+
__decorateParam(0, common.Body())
|
|
122
|
+
], AuthController.prototype, "resetPassword", 1);
|
|
123
|
+
AuthController = __decorateClass([
|
|
124
|
+
common.Controller("auth")
|
|
125
|
+
], AuthController);
|
|
126
|
+
|
|
127
|
+
// src/constants/tokens.ts
|
|
128
|
+
var AUTH_MODULE_OPTIONS = /* @__PURE__ */ Symbol("AUTH_MODULE_OPTIONS");
|
|
129
|
+
var AUTH_HOOKS = /* @__PURE__ */ Symbol("AUTH_HOOKS");
|
|
130
|
+
var AUTH_REPOSITORY = /* @__PURE__ */ Symbol("AUTH_REPOSITORY");
|
|
131
|
+
exports.DefaultAuthHooks = class DefaultAuthHooks {
|
|
132
|
+
async buildJwtPayload(account) {
|
|
133
|
+
return {
|
|
134
|
+
sub: account.id,
|
|
135
|
+
...account.email != null ? { email: account.email } : {},
|
|
136
|
+
...account.username != null ? { username: account.username } : {}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
async enrichMe(account) {
|
|
140
|
+
return {
|
|
141
|
+
id: account.id,
|
|
142
|
+
email: account.email,
|
|
143
|
+
username: account.username,
|
|
144
|
+
emailVerified: account.emailVerified,
|
|
145
|
+
disabled: account.disabled
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async onBeforeRegister(_input) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
async onAfterRegister(_account) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
async onAfterLogin(_account) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
exports.DefaultAuthHooks = __decorateClass([
|
|
159
|
+
common.Injectable()
|
|
160
|
+
], exports.DefaultAuthHooks);
|
|
161
|
+
|
|
162
|
+
// src/utils/duplicate-key.util.ts
|
|
163
|
+
function isDuplicateKeyError(error) {
|
|
164
|
+
return !!error && typeof error === "object" && "code" in error && error.code === 11e3;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/utils/identifier.util.ts
|
|
168
|
+
function normalizeIdentifier(value) {
|
|
169
|
+
return value.trim().toLowerCase();
|
|
170
|
+
}
|
|
171
|
+
function resolveRegisterIdentifier(input, field) {
|
|
172
|
+
const value = field === "email" ? input.email : input.username;
|
|
173
|
+
if (value == null || value.trim() === "") {
|
|
174
|
+
throw new Error(`Register input requires ${field}`);
|
|
175
|
+
}
|
|
176
|
+
return normalizeIdentifier(value);
|
|
177
|
+
}
|
|
178
|
+
function readAccountIdentifier(account, field) {
|
|
179
|
+
const value = field === "email" ? account.email : account.username;
|
|
180
|
+
return value != null ? normalizeIdentifier(value) : void 0;
|
|
181
|
+
}
|
|
182
|
+
function generateRawToken(byteLength = 32) {
|
|
183
|
+
return crypto.randomBytes(byteLength).toString("hex");
|
|
184
|
+
}
|
|
185
|
+
function hashToken(token) {
|
|
186
|
+
return crypto.createHash("sha256").update(token).digest("hex");
|
|
187
|
+
}
|
|
188
|
+
function expiresAtFromTtlMs(ttlMs) {
|
|
189
|
+
return new Date(Date.now() + ttlMs);
|
|
190
|
+
}
|
|
191
|
+
var DEFAULT_EMAIL_VERIFICATION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
192
|
+
var DEFAULT_PASSWORD_RESET_TTL_MS = 15 * 60 * 1e3;
|
|
193
|
+
|
|
194
|
+
// src/services/auth.service.ts
|
|
195
|
+
exports.AuthService = class AuthService {
|
|
196
|
+
constructor(authRepository, options, hooks, tokenService) {
|
|
197
|
+
this.authRepository = authRepository;
|
|
198
|
+
this.options = options;
|
|
199
|
+
this.hooks = hooks;
|
|
200
|
+
this.tokenService = tokenService;
|
|
201
|
+
}
|
|
202
|
+
get identifierField() {
|
|
203
|
+
return this.options.identifierField ?? "email";
|
|
204
|
+
}
|
|
205
|
+
get emailVerificationEnabled() {
|
|
206
|
+
return this.options.features?.emailVerification === true;
|
|
207
|
+
}
|
|
208
|
+
get passwordResetEnabled() {
|
|
209
|
+
return this.options.features?.passwordReset === true;
|
|
210
|
+
}
|
|
211
|
+
get rotateRefreshToken() {
|
|
212
|
+
return this.options.features?.refreshTokenRotation !== false;
|
|
213
|
+
}
|
|
214
|
+
resolveLoginIdentifier(dto) {
|
|
215
|
+
const value = this.identifierField === "email" ? dto.email : dto.username;
|
|
216
|
+
if (value == null || value.trim() === "") {
|
|
217
|
+
throw new common.BadRequestException(
|
|
218
|
+
`${this.identifierField} is required for login`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
return normalizeIdentifier(value);
|
|
222
|
+
}
|
|
223
|
+
async register(dto) {
|
|
224
|
+
this.assertEmailHookWhenVerificationEnabled();
|
|
225
|
+
const input = { password: dto.password };
|
|
226
|
+
if (dto.email != null) input.email = dto.email;
|
|
227
|
+
if (dto.username != null) input.username = dto.username;
|
|
228
|
+
await this.hooks.onBeforeRegister?.(input);
|
|
229
|
+
resolveRegisterIdentifier(input, this.identifierField);
|
|
230
|
+
this.assertRegisterEmailWhenVerificationEnabled(input);
|
|
231
|
+
const passwordHash = await bcrypt__namespace.hash(dto.password, 10);
|
|
232
|
+
try {
|
|
233
|
+
const account = await this.authRepository.create({
|
|
234
|
+
...input,
|
|
235
|
+
passwordHash,
|
|
236
|
+
emailVerified: !this.emailVerificationEnabled
|
|
237
|
+
});
|
|
238
|
+
await this.hooks.onAfterRegister?.(account);
|
|
239
|
+
if (this.emailVerificationEnabled) {
|
|
240
|
+
await this.sendVerificationEmail(account);
|
|
241
|
+
}
|
|
242
|
+
} catch (error) {
|
|
243
|
+
if (isDuplicateKeyError(error)) {
|
|
244
|
+
throw new common.UnauthorizedException(`${this.identifierField} already exists`);
|
|
245
|
+
}
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
return { registered: true };
|
|
249
|
+
}
|
|
250
|
+
async login(dto) {
|
|
251
|
+
const identifier = this.resolveLoginIdentifier(dto);
|
|
252
|
+
const account = await this.authRepository.findByIdentifierWithSecrets(
|
|
253
|
+
identifier
|
|
254
|
+
);
|
|
255
|
+
if (account?.passwordHash == null) {
|
|
256
|
+
throw new common.UnauthorizedException("Invalid credentials");
|
|
257
|
+
}
|
|
258
|
+
this.assertAccountActive(account);
|
|
259
|
+
const passwordMatches = await bcrypt__namespace.compare(
|
|
260
|
+
dto.password,
|
|
261
|
+
account.passwordHash
|
|
262
|
+
);
|
|
263
|
+
if (!passwordMatches) {
|
|
264
|
+
throw new common.UnauthorizedException("Invalid credentials");
|
|
265
|
+
}
|
|
266
|
+
return this.issueTokens(account);
|
|
267
|
+
}
|
|
268
|
+
async refresh(refreshToken) {
|
|
269
|
+
let payload;
|
|
270
|
+
try {
|
|
271
|
+
payload = await this.tokenService.verifyRefreshToken(refreshToken);
|
|
272
|
+
} catch {
|
|
273
|
+
throw new common.UnauthorizedException("Invalid refresh token");
|
|
274
|
+
}
|
|
275
|
+
const account = await this.authRepository.findByIdWithSecrets(payload.sub);
|
|
276
|
+
if (account?.refreshTokenHash == null) {
|
|
277
|
+
throw new common.UnauthorizedException("Invalid refresh token");
|
|
278
|
+
}
|
|
279
|
+
this.assertAccountActive(account);
|
|
280
|
+
const tokenMatches = await this.tokenService.compareRefreshToken(
|
|
281
|
+
refreshToken,
|
|
282
|
+
account.refreshTokenHash
|
|
283
|
+
);
|
|
284
|
+
if (!tokenMatches) {
|
|
285
|
+
throw new common.UnauthorizedException("Invalid refresh token");
|
|
286
|
+
}
|
|
287
|
+
return this.issueTokens(account);
|
|
288
|
+
}
|
|
289
|
+
async logout(authId) {
|
|
290
|
+
await this.authRepository.updateRefreshTokenHash(authId, null);
|
|
291
|
+
return { loggedOut: true };
|
|
292
|
+
}
|
|
293
|
+
async me(authId) {
|
|
294
|
+
const account = await this.authRepository.findById(authId);
|
|
295
|
+
if (account == null) {
|
|
296
|
+
throw new common.UnauthorizedException("Account not found");
|
|
297
|
+
}
|
|
298
|
+
if (this.hooks.enrichMe != null) {
|
|
299
|
+
return this.hooks.enrichMe(account);
|
|
300
|
+
}
|
|
301
|
+
return new exports.DefaultAuthHooks().enrichMe(account);
|
|
302
|
+
}
|
|
303
|
+
async verifyEmail(token) {
|
|
304
|
+
this.assertEmailVerificationEnabled();
|
|
305
|
+
const tokenHash = hashToken(token);
|
|
306
|
+
const account = await this.authRepository.findByEmailVerificationTokenHash(tokenHash);
|
|
307
|
+
if (account == null) {
|
|
308
|
+
throw new common.BadRequestException("TOKEN_INVALID_OR_EXPIRED");
|
|
309
|
+
}
|
|
310
|
+
await this.authRepository.markEmailVerified(account.id);
|
|
311
|
+
return { verified: true };
|
|
312
|
+
}
|
|
313
|
+
async forgotPassword(email) {
|
|
314
|
+
this.assertPasswordResetEnabled();
|
|
315
|
+
this.assertEmailHookWhenPasswordResetEnabled();
|
|
316
|
+
const normalizedEmail = normalizeIdentifier(email);
|
|
317
|
+
const account = await this.authRepository.findByEmail(normalizedEmail);
|
|
318
|
+
if (account != null) {
|
|
319
|
+
const rawToken = generateRawToken();
|
|
320
|
+
const tokenHash = hashToken(rawToken);
|
|
321
|
+
const expiresAt = expiresAtFromTtlMs(
|
|
322
|
+
this.options.passwordResetTokenTtlMs ?? DEFAULT_PASSWORD_RESET_TTL_MS
|
|
323
|
+
);
|
|
324
|
+
await this.authRepository.setResetToken(account.id, tokenHash, expiresAt);
|
|
325
|
+
await this.hooks.sendEmail("reset", normalizedEmail, rawToken);
|
|
326
|
+
}
|
|
327
|
+
return { sent: true };
|
|
328
|
+
}
|
|
329
|
+
async resetPassword(token, newPassword) {
|
|
330
|
+
this.assertPasswordResetEnabled();
|
|
331
|
+
const tokenHash = hashToken(token);
|
|
332
|
+
const account = await this.authRepository.findByResetTokenHash(tokenHash);
|
|
333
|
+
if (account == null) {
|
|
334
|
+
throw new common.BadRequestException("TOKEN_INVALID_OR_EXPIRED");
|
|
335
|
+
}
|
|
336
|
+
const passwordHash = await bcrypt__namespace.hash(newPassword, 10);
|
|
337
|
+
await this.authRepository.updatePasswordHash(account.id, passwordHash);
|
|
338
|
+
await this.authRepository.clearResetToken(account.id);
|
|
339
|
+
await this.authRepository.updateRefreshTokenHash(account.id, null);
|
|
340
|
+
return { reset: true };
|
|
341
|
+
}
|
|
342
|
+
assertAccountActive(account) {
|
|
343
|
+
if (account.disabled) {
|
|
344
|
+
throw new common.UnauthorizedException("ACCOUNT_DISABLED");
|
|
345
|
+
}
|
|
346
|
+
if (this.emailVerificationEnabled && !account.emailVerified) {
|
|
347
|
+
throw new common.UnauthorizedException("EMAIL_NOT_VERIFIED");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async issueTokens(account) {
|
|
351
|
+
const payload = await this.hooks.buildJwtPayload(account);
|
|
352
|
+
const tokens = await this.tokenService.signTokens({
|
|
353
|
+
...payload,
|
|
354
|
+
sub: account.id
|
|
355
|
+
});
|
|
356
|
+
if (this.rotateRefreshToken) {
|
|
357
|
+
const refreshTokenHash = await this.tokenService.hashRefreshToken(
|
|
358
|
+
tokens.refreshToken
|
|
359
|
+
);
|
|
360
|
+
await this.authRepository.updateRefreshTokenHash(
|
|
361
|
+
account.id,
|
|
362
|
+
refreshTokenHash
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
await this.hooks.onAfterLogin?.(account);
|
|
366
|
+
return tokens;
|
|
367
|
+
}
|
|
368
|
+
async sendVerificationEmail(account) {
|
|
369
|
+
const email = this.resolveAccountEmail(account);
|
|
370
|
+
if (email == null) return;
|
|
371
|
+
const rawToken = generateRawToken();
|
|
372
|
+
const tokenHash = hashToken(rawToken);
|
|
373
|
+
const expiresAt = expiresAtFromTtlMs(
|
|
374
|
+
this.options.emailVerificationTokenTtlMs ?? DEFAULT_EMAIL_VERIFICATION_TTL_MS
|
|
375
|
+
);
|
|
376
|
+
await this.authRepository.setEmailVerificationToken(
|
|
377
|
+
account.id,
|
|
378
|
+
tokenHash,
|
|
379
|
+
expiresAt
|
|
380
|
+
);
|
|
381
|
+
await this.hooks.sendEmail("verify", email, rawToken);
|
|
382
|
+
}
|
|
383
|
+
resolveAccountEmail(account) {
|
|
384
|
+
if (account.email != null && account.email.trim() !== "") {
|
|
385
|
+
return normalizeIdentifier(account.email);
|
|
386
|
+
}
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
assertRegisterEmailWhenVerificationEnabled(input) {
|
|
390
|
+
if (!this.emailVerificationEnabled) return;
|
|
391
|
+
const email = this.identifierField === "email" ? resolveRegisterIdentifier(input, "email") : input.email != null ? normalizeIdentifier(input.email) : null;
|
|
392
|
+
if (email == null || email.trim() === "") {
|
|
393
|
+
throw new common.BadRequestException(
|
|
394
|
+
"email is required when emailVerification feature is enabled"
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
assertEmailHookWhenVerificationEnabled() {
|
|
399
|
+
if (this.emailVerificationEnabled && this.hooks.sendEmail == null) {
|
|
400
|
+
throw new common.BadRequestException(
|
|
401
|
+
"emailVerification is enabled but AuthHooks.sendEmail is not implemented"
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
assertEmailHookWhenPasswordResetEnabled() {
|
|
406
|
+
if (this.passwordResetEnabled && this.hooks.sendEmail == null) {
|
|
407
|
+
throw new common.BadRequestException(
|
|
408
|
+
"passwordReset is enabled but AuthHooks.sendEmail is not implemented"
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
assertEmailVerificationEnabled() {
|
|
413
|
+
if (!this.emailVerificationEnabled) {
|
|
414
|
+
throw new common.NotFoundException();
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
assertPasswordResetEnabled() {
|
|
418
|
+
if (!this.passwordResetEnabled) {
|
|
419
|
+
throw new common.NotFoundException();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
getIdentifierForAccount(account) {
|
|
423
|
+
return readAccountIdentifier(account, this.identifierField);
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
exports.AuthService = __decorateClass([
|
|
427
|
+
common.Injectable(),
|
|
428
|
+
__decorateParam(0, common.Inject(AUTH_REPOSITORY)),
|
|
429
|
+
__decorateParam(1, common.Inject(AUTH_MODULE_OPTIONS)),
|
|
430
|
+
__decorateParam(2, common.Inject(AUTH_HOOKS))
|
|
431
|
+
], exports.AuthService);
|
|
432
|
+
exports.TokenService = class TokenService {
|
|
433
|
+
constructor(jwtService, options) {
|
|
434
|
+
this.jwtService = jwtService;
|
|
435
|
+
this.options = options;
|
|
436
|
+
}
|
|
437
|
+
async signTokens(payload) {
|
|
438
|
+
const accessExpiresIn = this.options.expiresIn ?? "1h";
|
|
439
|
+
const refreshExpiresIn = this.options.refreshExpiresIn ?? "7d";
|
|
440
|
+
const [accessToken, refreshToken] = await Promise.all([
|
|
441
|
+
this.jwtService.signAsync(
|
|
442
|
+
payload,
|
|
443
|
+
{
|
|
444
|
+
secret: this.options.secret,
|
|
445
|
+
expiresIn: accessExpiresIn
|
|
446
|
+
}
|
|
447
|
+
),
|
|
448
|
+
this.jwtService.signAsync(
|
|
449
|
+
payload,
|
|
450
|
+
{
|
|
451
|
+
secret: this.options.refreshSecret,
|
|
452
|
+
expiresIn: refreshExpiresIn
|
|
453
|
+
}
|
|
454
|
+
)
|
|
455
|
+
]);
|
|
456
|
+
return { accessToken, refreshToken };
|
|
457
|
+
}
|
|
458
|
+
async verifyRefreshToken(refreshToken) {
|
|
459
|
+
return this.jwtService.verifyAsync(refreshToken, {
|
|
460
|
+
secret: this.options.refreshSecret
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
async hashRefreshToken(refreshToken) {
|
|
464
|
+
return bcrypt__namespace.hash(refreshToken, 10);
|
|
465
|
+
}
|
|
466
|
+
async compareRefreshToken(refreshToken, hash3) {
|
|
467
|
+
return bcrypt__namespace.compare(refreshToken, hash3);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
exports.TokenService = __decorateClass([
|
|
471
|
+
common.Injectable(),
|
|
472
|
+
__decorateParam(1, common.Inject(AUTH_MODULE_OPTIONS))
|
|
473
|
+
], exports.TokenService);
|
|
474
|
+
var JwtStrategy = class extends passport.PassportStrategy(passportJwt.Strategy) {
|
|
475
|
+
constructor(options, authRepository) {
|
|
476
|
+
super({
|
|
477
|
+
jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeaderAsBearerToken(),
|
|
478
|
+
ignoreExpiration: false,
|
|
479
|
+
secretOrKey: options.secret
|
|
480
|
+
});
|
|
481
|
+
this.authRepository = authRepository;
|
|
482
|
+
}
|
|
483
|
+
async validate(payload) {
|
|
484
|
+
const account = await this.authRepository.findById(payload.sub);
|
|
485
|
+
if (account == null || account.disabled) {
|
|
486
|
+
throw new common.UnauthorizedException("Account not found or inactive");
|
|
487
|
+
}
|
|
488
|
+
return payload;
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
JwtStrategy = __decorateClass([
|
|
492
|
+
common.Injectable(),
|
|
493
|
+
__decorateParam(0, common.Inject(AUTH_MODULE_OPTIONS)),
|
|
494
|
+
__decorateParam(1, common.Inject(AUTH_REPOSITORY))
|
|
495
|
+
], JwtStrategy);
|
|
496
|
+
|
|
497
|
+
// src/auth.module.ts
|
|
498
|
+
function createAuthProviders(options) {
|
|
499
|
+
return [
|
|
500
|
+
{
|
|
501
|
+
provide: AUTH_MODULE_OPTIONS,
|
|
502
|
+
useValue: options
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
provide: AUTH_HOOKS,
|
|
506
|
+
inject: [AUTH_MODULE_OPTIONS],
|
|
507
|
+
useFactory: (opts) => {
|
|
508
|
+
const HooksClass = opts.hooks ?? exports.DefaultAuthHooks;
|
|
509
|
+
return new HooksClass();
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
exports.AuthService,
|
|
513
|
+
exports.TokenService,
|
|
514
|
+
JwtStrategy,
|
|
515
|
+
exports.JwtAuthGuard
|
|
516
|
+
];
|
|
517
|
+
}
|
|
518
|
+
function createAuthImports() {
|
|
519
|
+
return [
|
|
520
|
+
passport.PassportModule.register({ defaultStrategy: "jwt" }),
|
|
521
|
+
jwt.JwtModule.registerAsync({
|
|
522
|
+
inject: [AUTH_MODULE_OPTIONS],
|
|
523
|
+
useFactory: (opts) => ({
|
|
524
|
+
secret: opts.secret,
|
|
525
|
+
signOptions: { expiresIn: opts.expiresIn ?? "1h" }
|
|
526
|
+
})
|
|
527
|
+
})
|
|
528
|
+
];
|
|
529
|
+
}
|
|
530
|
+
function mergeImports(userImports) {
|
|
531
|
+
const merged = [...createAuthImports()];
|
|
532
|
+
if (userImports != null) {
|
|
533
|
+
merged.unshift(...userImports);
|
|
534
|
+
}
|
|
535
|
+
return merged;
|
|
536
|
+
}
|
|
537
|
+
exports.AuthModule = class AuthModule {
|
|
538
|
+
static forRoot(options) {
|
|
539
|
+
return {
|
|
540
|
+
module: exports.AuthModule,
|
|
541
|
+
global: true,
|
|
542
|
+
imports: createAuthImports(),
|
|
543
|
+
controllers: [AuthController],
|
|
544
|
+
providers: createAuthProviders(options),
|
|
545
|
+
exports: [
|
|
546
|
+
AUTH_MODULE_OPTIONS,
|
|
547
|
+
AUTH_HOOKS,
|
|
548
|
+
exports.AuthService,
|
|
549
|
+
exports.TokenService,
|
|
550
|
+
exports.JwtAuthGuard,
|
|
551
|
+
jwt.JwtModule,
|
|
552
|
+
passport.PassportModule
|
|
553
|
+
]
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
static forRootAsync(options) {
|
|
557
|
+
return {
|
|
558
|
+
module: exports.AuthModule,
|
|
559
|
+
global: true,
|
|
560
|
+
imports: mergeImports(options.imports),
|
|
561
|
+
controllers: [AuthController],
|
|
562
|
+
providers: [
|
|
563
|
+
{
|
|
564
|
+
provide: AUTH_MODULE_OPTIONS,
|
|
565
|
+
inject: options.inject ?? [],
|
|
566
|
+
useFactory: options.useFactory
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
provide: AUTH_HOOKS,
|
|
570
|
+
inject: [AUTH_MODULE_OPTIONS],
|
|
571
|
+
useFactory: (opts) => {
|
|
572
|
+
const HooksClass = opts.hooks ?? exports.DefaultAuthHooks;
|
|
573
|
+
return new HooksClass();
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
exports.AuthService,
|
|
577
|
+
exports.TokenService,
|
|
578
|
+
JwtStrategy,
|
|
579
|
+
exports.JwtAuthGuard
|
|
580
|
+
],
|
|
581
|
+
exports: [
|
|
582
|
+
AUTH_MODULE_OPTIONS,
|
|
583
|
+
AUTH_HOOKS,
|
|
584
|
+
exports.AuthService,
|
|
585
|
+
exports.TokenService,
|
|
586
|
+
exports.JwtAuthGuard,
|
|
587
|
+
jwt.JwtModule,
|
|
588
|
+
passport.PassportModule
|
|
589
|
+
]
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
exports.AuthModule = __decorateClass([
|
|
594
|
+
common.Module({})
|
|
595
|
+
], exports.AuthModule);
|
|
596
|
+
|
|
597
|
+
// src/dto/auth-tokens.dto.ts
|
|
598
|
+
var AuthTokensDto = class {
|
|
599
|
+
};
|
|
600
|
+
var ForgotPasswordDto = class {
|
|
601
|
+
};
|
|
602
|
+
__decorateClass([
|
|
603
|
+
classValidator.IsEmail()
|
|
604
|
+
], ForgotPasswordDto.prototype, "email", 2);
|
|
605
|
+
var LoginDto = class {
|
|
606
|
+
};
|
|
607
|
+
__decorateClass([
|
|
608
|
+
classValidator.IsOptional(),
|
|
609
|
+
classValidator.IsString(),
|
|
610
|
+
classValidator.Length(3, 255)
|
|
611
|
+
], LoginDto.prototype, "email", 2);
|
|
612
|
+
__decorateClass([
|
|
613
|
+
classValidator.IsOptional(),
|
|
614
|
+
classValidator.IsString(),
|
|
615
|
+
classValidator.Length(3, 50)
|
|
616
|
+
], LoginDto.prototype, "username", 2);
|
|
617
|
+
__decorateClass([
|
|
618
|
+
classValidator.IsString(),
|
|
619
|
+
classValidator.IsNotEmpty(),
|
|
620
|
+
classValidator.Length(8, 128)
|
|
621
|
+
], LoginDto.prototype, "password", 2);
|
|
622
|
+
var RefreshTokenDto = class {
|
|
623
|
+
};
|
|
624
|
+
__decorateClass([
|
|
625
|
+
classValidator.IsString(),
|
|
626
|
+
classValidator.IsNotEmpty()
|
|
627
|
+
], RefreshTokenDto.prototype, "refreshToken", 2);
|
|
628
|
+
|
|
629
|
+
// src/dto/register-ack.dto.ts
|
|
630
|
+
var RegisterAckDto = class {
|
|
631
|
+
};
|
|
632
|
+
var RegisterDto = class {
|
|
633
|
+
};
|
|
634
|
+
__decorateClass([
|
|
635
|
+
classValidator.IsOptional(),
|
|
636
|
+
classValidator.IsString(),
|
|
637
|
+
classValidator.Length(3, 255)
|
|
638
|
+
], RegisterDto.prototype, "email", 2);
|
|
639
|
+
__decorateClass([
|
|
640
|
+
classValidator.IsOptional(),
|
|
641
|
+
classValidator.IsString(),
|
|
642
|
+
classValidator.Length(3, 50),
|
|
643
|
+
classValidator.Matches(/^[a-zA-Z0-9._-]+$/)
|
|
644
|
+
], RegisterDto.prototype, "username", 2);
|
|
645
|
+
__decorateClass([
|
|
646
|
+
classValidator.IsString(),
|
|
647
|
+
classValidator.IsNotEmpty(),
|
|
648
|
+
classValidator.Length(8, 128)
|
|
649
|
+
], RegisterDto.prototype, "password", 2);
|
|
650
|
+
var ResetPasswordDto = class {
|
|
651
|
+
};
|
|
652
|
+
__decorateClass([
|
|
653
|
+
classValidator.IsString(),
|
|
654
|
+
classValidator.IsNotEmpty()
|
|
655
|
+
], ResetPasswordDto.prototype, "token", 2);
|
|
656
|
+
__decorateClass([
|
|
657
|
+
classValidator.IsString(),
|
|
658
|
+
classValidator.IsNotEmpty(),
|
|
659
|
+
classValidator.Length(8, 128)
|
|
660
|
+
], ResetPasswordDto.prototype, "newPassword", 2);
|
|
661
|
+
var VerifyEmailDto = class {
|
|
662
|
+
};
|
|
663
|
+
__decorateClass([
|
|
664
|
+
classValidator.IsString(),
|
|
665
|
+
classValidator.IsNotEmpty()
|
|
666
|
+
], VerifyEmailDto.prototype, "token", 2);
|
|
667
|
+
|
|
668
|
+
exports.AUTH_HOOKS = AUTH_HOOKS;
|
|
669
|
+
exports.AUTH_MODULE_OPTIONS = AUTH_MODULE_OPTIONS;
|
|
670
|
+
exports.AUTH_REPOSITORY = AUTH_REPOSITORY;
|
|
671
|
+
exports.AuthTokensDto = AuthTokensDto;
|
|
672
|
+
exports.CurrentUser = CurrentUser;
|
|
673
|
+
exports.ForgotPasswordDto = ForgotPasswordDto;
|
|
674
|
+
exports.LoginDto = LoginDto;
|
|
675
|
+
exports.RefreshTokenDto = RefreshTokenDto;
|
|
676
|
+
exports.RegisterAckDto = RegisterAckDto;
|
|
677
|
+
exports.RegisterDto = RegisterDto;
|
|
678
|
+
exports.ResetPasswordDto = ResetPasswordDto;
|
|
679
|
+
exports.VerifyEmailDto = VerifyEmailDto;
|
|
680
|
+
//# sourceMappingURL=index.cjs.map
|
|
681
|
+
//# sourceMappingURL=index.cjs.map
|