@nauth-toolkit/core 0.1.0 → 0.1.3
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 +30 -0
- package/package.json +7 -2
- 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
package/src/dto/signup.dto.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { IsEmail, IsString, MinLength, MaxLength, IsOptional, Matches } from 'class-validator';
|
|
2
|
-
import { Transform } from 'class-transformer';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* DTO for user signup with comprehensive validation
|
|
6
|
-
*
|
|
7
|
-
* Security:
|
|
8
|
-
* - All fields validated against DB constraints
|
|
9
|
-
* - Input sanitization applied automatically
|
|
10
|
-
* - Password strength enforced (8-128 chars)
|
|
11
|
-
* - Email/username uniqueness checked in service layer
|
|
12
|
-
*/
|
|
13
|
-
export class SignupDTO {
|
|
14
|
-
/**
|
|
15
|
-
* User email address
|
|
16
|
-
*
|
|
17
|
-
* Validation:
|
|
18
|
-
* - Valid email format (RFC 5322)
|
|
19
|
-
* - Max 255 characters (matches DB limit)
|
|
20
|
-
*
|
|
21
|
-
* Sanitization:
|
|
22
|
-
* - Trimmed and lowercased
|
|
23
|
-
*/
|
|
24
|
-
@IsEmail({}, { message: 'Invalid email format' })
|
|
25
|
-
@MaxLength(255, { message: 'Email must not exceed 255 characters' })
|
|
26
|
-
@Transform(({ value }) => {
|
|
27
|
-
if (typeof value === 'string') {
|
|
28
|
-
return value.trim().toLowerCase();
|
|
29
|
-
}
|
|
30
|
-
return value;
|
|
31
|
-
})
|
|
32
|
-
email!: string;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* User password
|
|
36
|
-
*
|
|
37
|
-
* Validation:
|
|
38
|
-
* - Min 8 characters
|
|
39
|
-
* - Max 128 characters (prevents DoS via bcrypt)
|
|
40
|
-
* - Additional policy checks in service layer
|
|
41
|
-
*
|
|
42
|
-
* Note: NOT trimmed (passwords can have leading/trailing spaces)
|
|
43
|
-
*/
|
|
44
|
-
@IsString({ message: 'Password must be a string' })
|
|
45
|
-
@MinLength(8, { message: 'Password must be at least 8 characters' })
|
|
46
|
-
@MaxLength(128, { message: 'Password must not exceed 128 characters' })
|
|
47
|
-
password!: string;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Optional username
|
|
51
|
-
*
|
|
52
|
-
* Validation:
|
|
53
|
-
* - 3-50 characters
|
|
54
|
-
* - Alphanumeric, underscores, and hyphens only
|
|
55
|
-
* - Max 255 characters (DB limit)
|
|
56
|
-
*
|
|
57
|
-
* Sanitization:
|
|
58
|
-
* - Trimmed
|
|
59
|
-
* - Case preserved (username can be case-sensitive per config)
|
|
60
|
-
*/
|
|
61
|
-
@IsOptional()
|
|
62
|
-
@IsString({ message: 'Username must be a string' })
|
|
63
|
-
@MinLength(3, { message: 'Username must be at least 3 characters' })
|
|
64
|
-
@MaxLength(255, { message: 'Username must not exceed 255 characters' })
|
|
65
|
-
@Matches(/^[a-zA-Z0-9_-]+$/, {
|
|
66
|
-
message: 'Username can only contain letters, numbers, underscores, and hyphens',
|
|
67
|
-
})
|
|
68
|
-
@Transform(({ value }) => {
|
|
69
|
-
if (typeof value === 'string') {
|
|
70
|
-
return value.trim().toLowerCase();
|
|
71
|
-
}
|
|
72
|
-
return value;
|
|
73
|
-
})
|
|
74
|
-
username?: string;
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Optional first name
|
|
78
|
-
*
|
|
79
|
-
* Validation:
|
|
80
|
-
* - 1-100 characters
|
|
81
|
-
* - Letters, spaces, hyphens, and apostrophes only
|
|
82
|
-
* - Max 100 characters (DB limit)
|
|
83
|
-
*
|
|
84
|
-
* Sanitization:
|
|
85
|
-
* - Trimmed
|
|
86
|
-
* - Title case preserved
|
|
87
|
-
*/
|
|
88
|
-
@IsOptional()
|
|
89
|
-
@IsString({ message: 'First name must be a string' })
|
|
90
|
-
@MinLength(1, { message: 'First name must be at least 1 character' })
|
|
91
|
-
@MaxLength(100, { message: 'First name must not exceed 100 characters' })
|
|
92
|
-
@Matches(/^[a-zA-Z\s\-']+$/, {
|
|
93
|
-
message: 'First name can only contain letters, spaces, hyphens, and apostrophes',
|
|
94
|
-
})
|
|
95
|
-
@Transform(({ value }) => {
|
|
96
|
-
if (typeof value === 'string') {
|
|
97
|
-
return value.trim();
|
|
98
|
-
}
|
|
99
|
-
return value;
|
|
100
|
-
})
|
|
101
|
-
firstName?: string;
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Optional last name
|
|
105
|
-
*
|
|
106
|
-
* Validation:
|
|
107
|
-
* - 1-100 characters
|
|
108
|
-
* - Letters, spaces, hyphens, and apostrophes only
|
|
109
|
-
* - Max 100 characters (DB limit)
|
|
110
|
-
*
|
|
111
|
-
* Sanitization:
|
|
112
|
-
* - Trimmed
|
|
113
|
-
* - Title case preserved
|
|
114
|
-
*/
|
|
115
|
-
@IsOptional()
|
|
116
|
-
@IsString({ message: 'Last name must be a string' })
|
|
117
|
-
@MinLength(1, { message: 'Last name must be at least 1 character' })
|
|
118
|
-
@MaxLength(100, { message: 'Last name must not exceed 100 characters' })
|
|
119
|
-
@Matches(/^[a-zA-Z\s\-']+$/, {
|
|
120
|
-
message: 'Last name can only contain letters, spaces, hyphens, and apostrophes',
|
|
121
|
-
})
|
|
122
|
-
@Transform(({ value }) => {
|
|
123
|
-
if (typeof value === 'string') {
|
|
124
|
-
return value.trim();
|
|
125
|
-
}
|
|
126
|
-
return value;
|
|
127
|
-
})
|
|
128
|
-
lastName?: string;
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Optional phone number
|
|
132
|
-
*
|
|
133
|
-
* Validation:
|
|
134
|
-
* - E.164 format (international standard)
|
|
135
|
-
* - MUST start with + (required for security)
|
|
136
|
-
* - Max 20 characters (DB limit)
|
|
137
|
-
* - Example: +14155552671, +61444567890
|
|
138
|
-
*
|
|
139
|
-
* Sanitization:
|
|
140
|
-
* - Whitespace removed
|
|
141
|
-
* - Only digits and leading + preserved
|
|
142
|
-
*
|
|
143
|
-
* Security:
|
|
144
|
-
* - Strict E.164 validation prevents SQL injection
|
|
145
|
-
* - Max length prevents oversized inputs
|
|
146
|
-
*
|
|
147
|
-
* Note: Using regex for E.164 format as IsPhoneNumber requires specific country codes
|
|
148
|
-
* and doesn't support international E.164 format validation directly
|
|
149
|
-
*/
|
|
150
|
-
@IsOptional()
|
|
151
|
-
@IsString({ message: 'Phone must be a string' })
|
|
152
|
-
@MaxLength(20, { message: 'Phone must not exceed 20 characters' })
|
|
153
|
-
@Matches(/^\+[1-9]\d{1,14}$/, {
|
|
154
|
-
message: 'Phone must be in E.164 format with + prefix (e.g., +14155552671)',
|
|
155
|
-
})
|
|
156
|
-
@Transform(({ value }) => {
|
|
157
|
-
if (typeof value === 'string') {
|
|
158
|
-
// Remove all whitespace and keep only digits and +
|
|
159
|
-
return value.replace(/\s/g, '');
|
|
160
|
-
}
|
|
161
|
-
return value;
|
|
162
|
-
})
|
|
163
|
-
phone?: string;
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Optional metadata (custom fields)
|
|
167
|
-
*
|
|
168
|
-
* Security:
|
|
169
|
-
* - Validated in service layer if used
|
|
170
|
-
* - Max depth/size limits should be enforced
|
|
171
|
-
*/
|
|
172
|
-
@IsOptional()
|
|
173
|
-
metadata?: Record<string, unknown>;
|
|
174
|
-
}
|
|
@@ -1,422 +0,0 @@
|
|
|
1
|
-
import { IsString, IsUUID, IsOptional, MaxLength, MinLength } from 'class-validator';
|
|
2
|
-
import { Transform } from 'class-transformer';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* DTO for getting social authentication URL
|
|
6
|
-
*
|
|
7
|
-
* Security:
|
|
8
|
-
* - Provider name validated as string
|
|
9
|
-
* - State parameter validated for length (CSRF protection)
|
|
10
|
-
*/
|
|
11
|
-
export class GetSocialAuthUrlDTO {
|
|
12
|
-
/**
|
|
13
|
-
* Social provider name (e.g., 'google', 'apple', 'facebook')
|
|
14
|
-
*
|
|
15
|
-
* Validation:
|
|
16
|
-
* - Must be non-empty string
|
|
17
|
-
* - Max 50 characters
|
|
18
|
-
*
|
|
19
|
-
* Sanitization:
|
|
20
|
-
* - Trimmed and lowercased
|
|
21
|
-
*/
|
|
22
|
-
@IsString({ message: 'Provider must be a string' })
|
|
23
|
-
@MaxLength(50, { message: 'Provider name must not exceed 50 characters' })
|
|
24
|
-
@Transform(({ value }) => {
|
|
25
|
-
if (typeof value === 'string') {
|
|
26
|
-
return value.trim().toLowerCase();
|
|
27
|
-
}
|
|
28
|
-
return value;
|
|
29
|
-
})
|
|
30
|
-
provider!: string;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Optional CSRF state parameter
|
|
34
|
-
*
|
|
35
|
-
* Validation:
|
|
36
|
-
* - Max 500 characters (typical state token length)
|
|
37
|
-
* - Optional field
|
|
38
|
-
*
|
|
39
|
-
* Sanitization:
|
|
40
|
-
* - Trimmed
|
|
41
|
-
*/
|
|
42
|
-
@IsOptional()
|
|
43
|
-
@IsString({ message: 'State must be a string' })
|
|
44
|
-
@MaxLength(500, { message: 'State must not exceed 500 characters' })
|
|
45
|
-
@Transform(({ value }) => {
|
|
46
|
-
if (typeof value === 'string') {
|
|
47
|
-
return value.trim();
|
|
48
|
-
}
|
|
49
|
-
return value;
|
|
50
|
-
})
|
|
51
|
-
state?: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Response DTO for getSocialAuthUrl
|
|
56
|
-
*/
|
|
57
|
-
export class GetSocialAuthUrlResponseDTO {
|
|
58
|
-
/**
|
|
59
|
-
* OAuth authorization URL
|
|
60
|
-
*/
|
|
61
|
-
url!: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* DTO for handling social authentication callback
|
|
66
|
-
*
|
|
67
|
-
* Security:
|
|
68
|
-
* - Provider name validated
|
|
69
|
-
* - Code validated for length
|
|
70
|
-
* - State validated for CSRF protection
|
|
71
|
-
*/
|
|
72
|
-
export class HandleSocialCallbackDTO {
|
|
73
|
-
/**
|
|
74
|
-
* Social provider name (e.g., 'google', 'apple', 'facebook')
|
|
75
|
-
*
|
|
76
|
-
* Validation:
|
|
77
|
-
* - Must be non-empty string
|
|
78
|
-
* - Max 50 characters
|
|
79
|
-
*
|
|
80
|
-
* Sanitization:
|
|
81
|
-
* - Trimmed and lowercased
|
|
82
|
-
*/
|
|
83
|
-
@IsString({ message: 'Provider must be a string' })
|
|
84
|
-
@MaxLength(50, { message: 'Provider name must not exceed 50 characters' })
|
|
85
|
-
@Transform(({ value }) => {
|
|
86
|
-
if (typeof value === 'string') {
|
|
87
|
-
return value.trim().toLowerCase();
|
|
88
|
-
}
|
|
89
|
-
return value;
|
|
90
|
-
})
|
|
91
|
-
provider!: string;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Authorization code from OAuth callback
|
|
95
|
-
*
|
|
96
|
-
* Validation:
|
|
97
|
-
* - Must be non-empty string
|
|
98
|
-
* - Max 1000 characters (OAuth codes can be long)
|
|
99
|
-
*
|
|
100
|
-
* Sanitization:
|
|
101
|
-
* - Trimmed
|
|
102
|
-
*/
|
|
103
|
-
@IsString({ message: 'Code must be a string' })
|
|
104
|
-
@MaxLength(1000, { message: 'Authorization code must not exceed 1000 characters' })
|
|
105
|
-
@Transform(({ value }) => {
|
|
106
|
-
if (typeof value === 'string') {
|
|
107
|
-
return value.trim();
|
|
108
|
-
}
|
|
109
|
-
return value;
|
|
110
|
-
})
|
|
111
|
-
code!: string;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* State parameter from OAuth callback (for CSRF validation)
|
|
115
|
-
*
|
|
116
|
-
* Validation:
|
|
117
|
-
* - Must be non-empty string
|
|
118
|
-
* - Max 500 characters
|
|
119
|
-
*
|
|
120
|
-
* Sanitization:
|
|
121
|
-
* - Trimmed
|
|
122
|
-
*/
|
|
123
|
-
@IsString({ message: 'State must be a string' })
|
|
124
|
-
@MaxLength(500, { message: 'State must not exceed 500 characters' })
|
|
125
|
-
@Transform(({ value }) => {
|
|
126
|
-
if (typeof value === 'string') {
|
|
127
|
-
return value.trim();
|
|
128
|
-
}
|
|
129
|
-
return value;
|
|
130
|
-
})
|
|
131
|
-
state!: string;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* DTO for linking social account
|
|
136
|
-
*
|
|
137
|
-
* Security:
|
|
138
|
-
* - User ID validated as UUID v4
|
|
139
|
-
* - Provider name validated
|
|
140
|
-
* - Code and state validated for length
|
|
141
|
-
*/
|
|
142
|
-
export class LinkSocialAccountDTO {
|
|
143
|
-
/**
|
|
144
|
-
* User identifier (UUID v4)
|
|
145
|
-
*
|
|
146
|
-
* Validation:
|
|
147
|
-
* - Must be valid UUID v4 format
|
|
148
|
-
*
|
|
149
|
-
* Sanitization:
|
|
150
|
-
* - Trimmed and lowercased
|
|
151
|
-
*/
|
|
152
|
-
@IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
|
|
153
|
-
@Transform(({ value }) => {
|
|
154
|
-
if (typeof value === 'string') {
|
|
155
|
-
return value.trim().toLowerCase();
|
|
156
|
-
}
|
|
157
|
-
return value;
|
|
158
|
-
})
|
|
159
|
-
userId!: string;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Social provider name (e.g., 'google', 'apple', 'facebook')
|
|
163
|
-
*
|
|
164
|
-
* Validation:
|
|
165
|
-
* - Must be non-empty string
|
|
166
|
-
* - Max 50 characters
|
|
167
|
-
*
|
|
168
|
-
* Sanitization:
|
|
169
|
-
* - Trimmed and lowercased
|
|
170
|
-
*/
|
|
171
|
-
@IsString({ message: 'Provider must be a string' })
|
|
172
|
-
@MaxLength(50, { message: 'Provider name must not exceed 50 characters' })
|
|
173
|
-
@Transform(({ value }) => {
|
|
174
|
-
if (typeof value === 'string') {
|
|
175
|
-
return value.trim().toLowerCase();
|
|
176
|
-
}
|
|
177
|
-
return value;
|
|
178
|
-
})
|
|
179
|
-
provider!: string;
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Authorization code from OAuth callback
|
|
183
|
-
*
|
|
184
|
-
* Validation:
|
|
185
|
-
* - Must be non-empty string
|
|
186
|
-
* - Max 1000 characters
|
|
187
|
-
*
|
|
188
|
-
* Sanitization:
|
|
189
|
-
* - Trimmed
|
|
190
|
-
*/
|
|
191
|
-
@IsString({ message: 'Code must be a string' })
|
|
192
|
-
@MaxLength(1000, { message: 'Authorization code must not exceed 1000 characters' })
|
|
193
|
-
@Transform(({ value }) => {
|
|
194
|
-
if (typeof value === 'string') {
|
|
195
|
-
return value.trim();
|
|
196
|
-
}
|
|
197
|
-
return value;
|
|
198
|
-
})
|
|
199
|
-
code!: string;
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* State parameter from OAuth callback (for CSRF validation)
|
|
203
|
-
*
|
|
204
|
-
* Validation:
|
|
205
|
-
* - Must be non-empty string
|
|
206
|
-
* - Max 500 characters
|
|
207
|
-
*
|
|
208
|
-
* Sanitization:
|
|
209
|
-
* - Trimmed
|
|
210
|
-
*/
|
|
211
|
-
@IsString({ message: 'State must be a string' })
|
|
212
|
-
@MaxLength(500, { message: 'State must not exceed 500 characters' })
|
|
213
|
-
@Transform(({ value }) => {
|
|
214
|
-
if (typeof value === 'string') {
|
|
215
|
-
return value.trim();
|
|
216
|
-
}
|
|
217
|
-
return value;
|
|
218
|
-
})
|
|
219
|
-
state!: string;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Response DTO for linkSocialAccount
|
|
224
|
-
*/
|
|
225
|
-
export class LinkSocialAccountResponseDTO {
|
|
226
|
-
/**
|
|
227
|
-
* Success message
|
|
228
|
-
*/
|
|
229
|
-
message!: string;
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Provider name
|
|
233
|
-
*/
|
|
234
|
-
provider!: string;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* DTO for getting linked social accounts
|
|
239
|
-
*
|
|
240
|
-
* Security:
|
|
241
|
-
* - User ID validated as UUID v4
|
|
242
|
-
*/
|
|
243
|
-
export class GetLinkedAccountsDTO {
|
|
244
|
-
/**
|
|
245
|
-
* User identifier (UUID v4)
|
|
246
|
-
*
|
|
247
|
-
* Validation:
|
|
248
|
-
* - Must be valid UUID v4 format
|
|
249
|
-
*
|
|
250
|
-
* Sanitization:
|
|
251
|
-
* - Trimmed and lowercased
|
|
252
|
-
*/
|
|
253
|
-
@IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
|
|
254
|
-
@Transform(({ value }) => {
|
|
255
|
-
if (typeof value === 'string') {
|
|
256
|
-
return value.trim().toLowerCase();
|
|
257
|
-
}
|
|
258
|
-
return value;
|
|
259
|
-
})
|
|
260
|
-
userId!: string;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Response DTO for getLinkedAccounts
|
|
265
|
-
*/
|
|
266
|
-
export class GetLinkedAccountsResponseDTO {
|
|
267
|
-
/**
|
|
268
|
-
* Array of linked social accounts
|
|
269
|
-
*/
|
|
270
|
-
accounts!: Array<{
|
|
271
|
-
provider: string;
|
|
272
|
-
providerEmail?: string;
|
|
273
|
-
linkedAt: Date;
|
|
274
|
-
lastUsedAt?: Date;
|
|
275
|
-
}>;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* DTO for unlinking social account
|
|
280
|
-
*
|
|
281
|
-
* Security:
|
|
282
|
-
* - User ID validated as UUID v4
|
|
283
|
-
* - Provider name validated
|
|
284
|
-
*/
|
|
285
|
-
export class UnlinkSocialAccountDTO {
|
|
286
|
-
/**
|
|
287
|
-
* User identifier (UUID v4)
|
|
288
|
-
*
|
|
289
|
-
* Validation:
|
|
290
|
-
* - Must be valid UUID v4 format
|
|
291
|
-
*
|
|
292
|
-
* Sanitization:
|
|
293
|
-
* - Trimmed and lowercased
|
|
294
|
-
*/
|
|
295
|
-
@IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
|
|
296
|
-
@Transform(({ value }) => {
|
|
297
|
-
if (typeof value === 'string') {
|
|
298
|
-
return value.trim().toLowerCase();
|
|
299
|
-
}
|
|
300
|
-
return value;
|
|
301
|
-
})
|
|
302
|
-
userId!: string;
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Social provider name (e.g., 'google', 'apple', 'facebook')
|
|
306
|
-
*
|
|
307
|
-
* Validation:
|
|
308
|
-
* - Must be non-empty string
|
|
309
|
-
* - Max 50 characters
|
|
310
|
-
*
|
|
311
|
-
* Sanitization:
|
|
312
|
-
* - Trimmed and lowercased
|
|
313
|
-
*/
|
|
314
|
-
@IsString({ message: 'Provider must be a string' })
|
|
315
|
-
@MaxLength(50, { message: 'Provider name must not exceed 50 characters' })
|
|
316
|
-
@Transform(({ value }) => {
|
|
317
|
-
if (typeof value === 'string') {
|
|
318
|
-
return value.trim().toLowerCase();
|
|
319
|
-
}
|
|
320
|
-
return value;
|
|
321
|
-
})
|
|
322
|
-
provider!: string;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Response DTO for unlinkSocialAccount
|
|
327
|
-
*/
|
|
328
|
-
export class UnlinkSocialAccountResponseDTO {
|
|
329
|
-
/**
|
|
330
|
-
* Success message
|
|
331
|
-
*/
|
|
332
|
-
message!: string;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* DTO for checking if user can set password
|
|
337
|
-
*
|
|
338
|
-
* Security:
|
|
339
|
-
* - User ID validated as UUID v4
|
|
340
|
-
*/
|
|
341
|
-
export class CanSetPasswordDTO {
|
|
342
|
-
/**
|
|
343
|
-
* User identifier (UUID v4)
|
|
344
|
-
*
|
|
345
|
-
* Validation:
|
|
346
|
-
* - Must be valid UUID v4 format
|
|
347
|
-
*
|
|
348
|
-
* Sanitization:
|
|
349
|
-
* - Trimmed and lowercased
|
|
350
|
-
*/
|
|
351
|
-
@IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
|
|
352
|
-
@Transform(({ value }) => {
|
|
353
|
-
if (typeof value === 'string') {
|
|
354
|
-
return value.trim().toLowerCase();
|
|
355
|
-
}
|
|
356
|
-
return value;
|
|
357
|
-
})
|
|
358
|
-
userId!: string;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Response DTO for canSetPassword
|
|
363
|
-
*/
|
|
364
|
-
export class CanSetPasswordResponseDTO {
|
|
365
|
-
/**
|
|
366
|
-
* Whether user can set password
|
|
367
|
-
*/
|
|
368
|
-
canSetPassword!: boolean;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* DTO for setting password for social-only user
|
|
373
|
-
*
|
|
374
|
-
* Security:
|
|
375
|
-
* - User ID validated as UUID v4
|
|
376
|
-
* - Password validated for strength (delegated to AuthService)
|
|
377
|
-
*/
|
|
378
|
-
export class SetPasswordForSocialUserDTO {
|
|
379
|
-
/**
|
|
380
|
-
* User identifier (UUID v4)
|
|
381
|
-
*
|
|
382
|
-
* Validation:
|
|
383
|
-
* - Must be valid UUID v4 format
|
|
384
|
-
*
|
|
385
|
-
* Sanitization:
|
|
386
|
-
* - Trimmed and lowercased
|
|
387
|
-
*/
|
|
388
|
-
@IsUUID('4', { message: 'User ID must be a valid UUID v4 format' })
|
|
389
|
-
@Transform(({ value }) => {
|
|
390
|
-
if (typeof value === 'string') {
|
|
391
|
-
return value.trim().toLowerCase();
|
|
392
|
-
}
|
|
393
|
-
return value;
|
|
394
|
-
})
|
|
395
|
-
userId!: string;
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* New password
|
|
399
|
-
*
|
|
400
|
-
* Validation:
|
|
401
|
-
* - Must be non-empty string
|
|
402
|
-
* - Min 1 character (actual validation in AuthService)
|
|
403
|
-
* - Max 128 characters (matches DB constraint)
|
|
404
|
-
*
|
|
405
|
-
* Sanitization:
|
|
406
|
-
* - Not trimmed (passwords may have leading/trailing spaces intentionally)
|
|
407
|
-
*/
|
|
408
|
-
@IsString({ message: 'Password must be a string' })
|
|
409
|
-
@MinLength(1, { message: 'Password is required' })
|
|
410
|
-
@MaxLength(128, { message: 'Password must not exceed 128 characters' })
|
|
411
|
-
password!: string;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* Response DTO for setPasswordForSocialUser
|
|
416
|
-
*/
|
|
417
|
-
export class SetPasswordForSocialUserResponseDTO {
|
|
418
|
-
/**
|
|
419
|
-
* Success message
|
|
420
|
-
*/
|
|
421
|
-
message!: string;
|
|
422
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trust Device Response DTO
|
|
3
|
-
*
|
|
4
|
-
* Response DTO for trusting a device.
|
|
5
|
-
* No validators needed - this is generated internally by the library.
|
|
6
|
-
*
|
|
7
|
-
* Security:
|
|
8
|
-
* - Device token should be stored securely on client
|
|
9
|
-
* - Used for MFA bypass on trusted devices
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* const result = await authService.trustDevice();
|
|
14
|
-
* // Returns: { deviceToken: 'device-token-string' }
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Response DTO for trust device
|
|
20
|
-
*/
|
|
21
|
-
export class TrustDeviceResponseDTO {
|
|
22
|
-
/**
|
|
23
|
-
* Device trust token
|
|
24
|
-
*
|
|
25
|
-
* Note: Store this token securely on the client device
|
|
26
|
-
*
|
|
27
|
-
* @example "device-token-uuid-string"
|
|
28
|
-
*/
|
|
29
|
-
deviceToken!: string;
|
|
30
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trust Device DTO
|
|
3
|
-
*
|
|
4
|
-
* Note: No request DTO needed - sessionId is automatically extracted from JWT token context
|
|
5
|
-
* via ClientInfoService, similar to how IP address and user agent are handled.
|
|
6
|
-
*
|
|
7
|
-
* This file is kept for backward compatibility but TrustDeviceDTO is no longer used.
|
|
8
|
-
* The trustDevice() method now takes no parameters.
|
|
9
|
-
*/
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Update User Attributes Request DTO
|
|
3
|
-
*
|
|
4
|
-
* Request DTO for updating user profile information (includes user sub).
|
|
5
|
-
*
|
|
6
|
-
* Security:
|
|
7
|
-
* - User sub validated (UUID)
|
|
8
|
-
* - All fields validated according to UserUpdateDTO rules
|
|
9
|
-
* - Uniqueness constraints enforced
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* const result = await authService.updateUserAttributes({
|
|
14
|
-
* sub: 'user-uuid',
|
|
15
|
-
* username: 'newusername',
|
|
16
|
-
* firstName: 'John',
|
|
17
|
-
* lastName: 'Doe'
|
|
18
|
-
* });
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import { IsUUID } from 'class-validator';
|
|
23
|
-
import { Transform } from 'class-transformer';
|
|
24
|
-
import { UserUpdateDTO } from './user-update.dto';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Request DTO for updating user attributes (includes user sub)
|
|
28
|
-
*/
|
|
29
|
-
export class UpdateUserAttributesRequestDTO extends UserUpdateDTO {
|
|
30
|
-
/**
|
|
31
|
-
* User's unique identifier (UUID v4)
|
|
32
|
-
*
|
|
33
|
-
* Validation:
|
|
34
|
-
* - Must be a valid UUID v4 format
|
|
35
|
-
* - Matches DB constraint: char(36) or uuid
|
|
36
|
-
*
|
|
37
|
-
* Sanitization:
|
|
38
|
-
* - Trimmed
|
|
39
|
-
* - Lowercased for consistency
|
|
40
|
-
*
|
|
41
|
-
* @example "a21b654c-2746-4168-acee-c175083a65cd"
|
|
42
|
-
*/
|
|
43
|
-
@IsUUID('4', { message: 'User sub must be a valid UUID v4 format' })
|
|
44
|
-
@Transform(({ value }) => {
|
|
45
|
-
if (typeof value === 'string') {
|
|
46
|
-
return value.trim().toLowerCase();
|
|
47
|
-
}
|
|
48
|
-
return value;
|
|
49
|
-
})
|
|
50
|
-
sub!: string;
|
|
51
|
-
}
|