rl-core-api 0.11.3 → 0.12.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/dist/core/config/env.schema.d.ts +1 -0
- package/dist/core/config/env.schema.js +5 -0
- package/dist/features/auth/domain/auth.service.d.ts +2 -1
- package/dist/features/auth/domain/auth.service.js +6 -5
- package/dist/features/auth/domain/token.service.d.ts +4 -2
- package/dist/features/auth/domain/token.service.js +10 -4
- package/dist/features/auth/presentation/auth.controller.js +2 -1
- package/package.json +1 -1
|
@@ -30,6 +30,7 @@ export declare const envSchema: z.ZodObject<{
|
|
|
30
30
|
JWT_ACCESS_EXPIRES: z.ZodDefault<z.ZodString>;
|
|
31
31
|
JWT_PENDING_EXPIRES: z.ZodDefault<z.ZodString>;
|
|
32
32
|
JWT_REFRESH_EXPIRES_MINUTES: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
33
|
+
JWT_REFRESH_MOBILE_EXPIRES_MINUTES: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
33
34
|
TOTP_ENC_KEY: z.ZodString;
|
|
34
35
|
COOKIE_SECURE: z.ZodDefault<z.ZodPipe<z.ZodEnum<{
|
|
35
36
|
true: "true";
|
|
@@ -37,6 +37,11 @@ exports.envSchema = zod_1.z
|
|
|
37
37
|
.int()
|
|
38
38
|
.positive()
|
|
39
39
|
.default(360),
|
|
40
|
+
JWT_REFRESH_MOBILE_EXPIRES_MINUTES: zod_1.z.coerce
|
|
41
|
+
.number()
|
|
42
|
+
.int()
|
|
43
|
+
.positive()
|
|
44
|
+
.default(43_200),
|
|
40
45
|
TOTP_ENC_KEY: zod_1.z
|
|
41
46
|
.string()
|
|
42
47
|
.length(64, "TOTP_ENC_KEY deve ter 64 chars hex (32 bytes)"),
|
|
@@ -4,6 +4,7 @@ import { EnvService } from "../../../core/config/env.service";
|
|
|
4
4
|
import { MailerService } from "../../../core/mailer/mailer.service";
|
|
5
5
|
import { PasswordTokenPurpose, PasswordTokenStatus, TokenService } from "./token.service";
|
|
6
6
|
import { TotpSetup, TwoFactorService } from "./twoFactor.service";
|
|
7
|
+
import { ClientType } from "../presentation/commands/clientType.enum";
|
|
7
8
|
import { LoginCommand } from "../presentation/commands/login.command";
|
|
8
9
|
import { VerifyTwoFactorCommand } from "../presentation/commands/twoFactor.command";
|
|
9
10
|
import { RbacService } from "../../rbac/domain/rbac.service";
|
|
@@ -54,7 +55,7 @@ export declare class AuthService {
|
|
|
54
55
|
}>;
|
|
55
56
|
verifyTwoFactor(dto: VerifyTwoFactorCommand, ctx: RequestCtx): Promise<VerifiedSession>;
|
|
56
57
|
regenerateBackupCodes(userId: string, code: string): Promise<string[]>;
|
|
57
|
-
refresh(rawToken: string | undefined, ctx: RequestCtx): Promise<RefreshedTokens>;
|
|
58
|
+
refresh(rawToken: string | undefined, ctx: RequestCtx, client?: ClientType): Promise<RefreshedTokens>;
|
|
58
59
|
logout(rawRefreshToken?: string): Promise<void>;
|
|
59
60
|
forgotPassword(email: string): Promise<void>;
|
|
60
61
|
inspectPasswordToken(token: string): Promise<PasswordTokenCheck>;
|
|
@@ -20,6 +20,7 @@ const codedError_util_1 = require("../../../core/utils/codedError.util");
|
|
|
20
20
|
const hash_util_1 = require("../../../core/utils/hash.util");
|
|
21
21
|
const token_service_1 = require("./token.service");
|
|
22
22
|
const twoFactor_service_1 = require("./twoFactor.service");
|
|
23
|
+
const clientType_enum_1 = require("../presentation/commands/clientType.enum");
|
|
23
24
|
const rbac_service_1 = require("../../rbac/domain/rbac.service");
|
|
24
25
|
const users_service_1 = require("../../users/domain/users.service");
|
|
25
26
|
const BACKUP_FORMAT = /^[A-Za-z0-9]{4}-[A-Za-z0-9]{4}$/;
|
|
@@ -150,7 +151,7 @@ let AuthService = class AuthService {
|
|
|
150
151
|
user.backupCodes = remainingBackup;
|
|
151
152
|
}
|
|
152
153
|
await this.users.save(user);
|
|
153
|
-
const tokens = await this.finalizeLogin(user, ctx);
|
|
154
|
+
const tokens = await this.finalizeLogin(user, ctx, dto.client ?? clientType_enum_1.ClientType.WEB);
|
|
154
155
|
return { ...tokens, backupCodes };
|
|
155
156
|
}
|
|
156
157
|
async regenerateBackupCodes(userId, code) {
|
|
@@ -170,11 +171,11 @@ let AuthService = class AuthService {
|
|
|
170
171
|
await this.users.save(user);
|
|
171
172
|
return generated.plain;
|
|
172
173
|
}
|
|
173
|
-
async refresh(rawToken, ctx) {
|
|
174
|
+
async refresh(rawToken, ctx, client = clientType_enum_1.ClientType.WEB) {
|
|
174
175
|
if (!rawToken) {
|
|
175
176
|
throw new common_1.UnauthorizedException("Refresh token ausente");
|
|
176
177
|
}
|
|
177
|
-
const { userId, rawToken: newRefresh } = await this.tokens.rotateRefreshToken(rawToken, ctx);
|
|
178
|
+
const { userId, rawToken: newRefresh } = await this.tokens.rotateRefreshToken(rawToken, ctx, client);
|
|
178
179
|
const user = await this.users.findById(userId);
|
|
179
180
|
if (!user.isActive) {
|
|
180
181
|
throw accountInactive();
|
|
@@ -284,9 +285,9 @@ let AuthService = class AuthService {
|
|
|
284
285
|
mustChangePassword: user.mustChangePassword,
|
|
285
286
|
};
|
|
286
287
|
}
|
|
287
|
-
async finalizeLogin(user, ctx) {
|
|
288
|
+
async finalizeLogin(user, ctx, client) {
|
|
288
289
|
const accessToken = await this.signAccessToken(user);
|
|
289
|
-
const { rawToken } = await this.tokens.issueRefreshToken(user.id, undefined, ctx);
|
|
290
|
+
const { rawToken } = await this.tokens.issueRefreshToken(user.id, undefined, ctx, client);
|
|
290
291
|
return {
|
|
291
292
|
accessToken,
|
|
292
293
|
refreshToken: rawToken,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EnvService } from "../../../core/config/env.service";
|
|
2
2
|
import { AuthTokenRepository } from "../infra/repositories/authToken.repository";
|
|
3
3
|
import { TokenType } from "../infra/schema/authToken.schema";
|
|
4
|
+
import { ClientType } from "../presentation/commands/clientType.enum";
|
|
4
5
|
export interface RotationResult {
|
|
5
6
|
userId: string;
|
|
6
7
|
rawToken: string;
|
|
@@ -29,17 +30,18 @@ export declare class TokenService {
|
|
|
29
30
|
constructor(repo: AuthTokenRepository, env: EnvService);
|
|
30
31
|
private persist;
|
|
31
32
|
private minutesFromNow;
|
|
33
|
+
private refreshMinutes;
|
|
32
34
|
issueRefreshToken(userId: string, family?: string, ctx?: {
|
|
33
35
|
ipAddress?: string;
|
|
34
36
|
userAgent?: string;
|
|
35
|
-
}): Promise<{
|
|
37
|
+
}, client?: ClientType): Promise<{
|
|
36
38
|
rawToken: string;
|
|
37
39
|
family: string;
|
|
38
40
|
}>;
|
|
39
41
|
rotateRefreshToken(rawToken: string, ctx?: {
|
|
40
42
|
ipAddress?: string;
|
|
41
43
|
userAgent?: string;
|
|
42
|
-
}): Promise<RotationResult>;
|
|
44
|
+
}, client?: ClientType): Promise<RotationResult>;
|
|
43
45
|
revokeFamily(family: string): Promise<void>;
|
|
44
46
|
revokeAllRefresh(userId: string): Promise<void>;
|
|
45
47
|
revokeByRawToken(rawToken: string): Promise<void>;
|
|
@@ -18,6 +18,7 @@ const env_service_1 = require("../../../core/config/env.service");
|
|
|
18
18
|
const hash_util_1 = require("../../../core/utils/hash.util");
|
|
19
19
|
const authToken_repository_1 = require("../infra/repositories/authToken.repository");
|
|
20
20
|
const authToken_schema_1 = require("../infra/schema/authToken.schema");
|
|
21
|
+
const clientType_enum_1 = require("../presentation/commands/clientType.enum");
|
|
21
22
|
var PasswordTokenStatus;
|
|
22
23
|
(function (PasswordTokenStatus) {
|
|
23
24
|
PasswordTokenStatus["VALID"] = "valid";
|
|
@@ -49,7 +50,12 @@ let TokenService = TokenService_1 = class TokenService {
|
|
|
49
50
|
minutesFromNow(minutes) {
|
|
50
51
|
return new Date(Date.now() + minutes * 60_000);
|
|
51
52
|
}
|
|
52
|
-
|
|
53
|
+
refreshMinutes(client) {
|
|
54
|
+
return client === clientType_enum_1.ClientType.MOBILE
|
|
55
|
+
? this.env.get("JWT_REFRESH_MOBILE_EXPIRES_MINUTES")
|
|
56
|
+
: this.env.get("JWT_REFRESH_EXPIRES_MINUTES");
|
|
57
|
+
}
|
|
58
|
+
async issueRefreshToken(userId, family, ctx, client = clientType_enum_1.ClientType.WEB) {
|
|
53
59
|
const rawToken = (0, hash_util_1.randomToken)(48);
|
|
54
60
|
const fam = family ?? (0, uuid_1.v7)();
|
|
55
61
|
await this.persist({
|
|
@@ -57,13 +63,13 @@ let TokenService = TokenService_1 = class TokenService {
|
|
|
57
63
|
rawToken,
|
|
58
64
|
type: authToken_schema_1.TokenType.REFRESH_TOKEN,
|
|
59
65
|
family: fam,
|
|
60
|
-
expiresAt: this.minutesFromNow(this.
|
|
66
|
+
expiresAt: this.minutesFromNow(this.refreshMinutes(client)),
|
|
61
67
|
ipAddress: ctx?.ipAddress,
|
|
62
68
|
userAgent: ctx?.userAgent,
|
|
63
69
|
});
|
|
64
70
|
return { rawToken, family: fam };
|
|
65
71
|
}
|
|
66
|
-
async rotateRefreshToken(rawToken, ctx) {
|
|
72
|
+
async rotateRefreshToken(rawToken, ctx, client = clientType_enum_1.ClientType.WEB) {
|
|
67
73
|
const tokenHash = (0, hash_util_1.sha256)(rawToken);
|
|
68
74
|
const stored = await this.repo.findOne({
|
|
69
75
|
where: { tokenHash, type: authToken_schema_1.TokenType.REFRESH_TOKEN },
|
|
@@ -83,7 +89,7 @@ let TokenService = TokenService_1 = class TokenService {
|
|
|
83
89
|
}
|
|
84
90
|
stored.used = true;
|
|
85
91
|
await this.repo.save(stored);
|
|
86
|
-
const { rawToken: newRaw, family } = await this.issueRefreshToken(stored.userId, stored.family ?? undefined, ctx);
|
|
92
|
+
const { rawToken: newRaw, family } = await this.issueRefreshToken(stored.userId, stored.family ?? undefined, ctx, client);
|
|
87
93
|
return { userId: stored.userId, rawToken: newRaw, family };
|
|
88
94
|
}
|
|
89
95
|
async revokeFamily(family) {
|
|
@@ -63,7 +63,8 @@ let AuthController = class AuthController {
|
|
|
63
63
|
async refresh(dto, req, res) {
|
|
64
64
|
const cookies = req.cookies;
|
|
65
65
|
const raw = dto.refreshToken ?? cookies?.[cookie_util_1.REFRESH_COOKIE];
|
|
66
|
-
const
|
|
66
|
+
const client = dto.refreshToken ? clientType_enum_1.ClientType.MOBILE : clientType_enum_1.ClientType.WEB;
|
|
67
|
+
const tokens = await this.auth.refresh(raw, ctxFrom(req), client);
|
|
67
68
|
if (dto.refreshToken) {
|
|
68
69
|
return { ok: true, ...tokens };
|
|
69
70
|
}
|
package/package.json
CHANGED