@plyaz/auth 1.0.0 → 1.0.2

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.
Files changed (99) hide show
  1. package/commits.txt +3 -3
  2. package/dist/common/index.cjs +3 -1
  3. package/dist/common/index.cjs.map +1 -1
  4. package/dist/common/index.mjs +3 -1
  5. package/dist/common/index.mjs.map +1 -1
  6. package/dist/index.cjs +424 -154
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.mjs +421 -152
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +2 -1
  11. package/release_message.txt +28 -0
  12. package/src/adapters/auth-adapter-factory.ts +4 -3
  13. package/src/adapters/auth-adapter.mapper.ts +2 -2
  14. package/src/adapters/base-auth.adapter.ts +17 -9
  15. package/src/adapters/clerk/clerk.adapter.ts +9 -12
  16. package/src/adapters/custom/custom.adapter.ts +19 -10
  17. package/src/adapters/index.ts +0 -1
  18. package/src/adapters/next-auth/authOptions.ts +20 -16
  19. package/src/adapters/next-auth/next-auth.adapter.ts +13 -15
  20. package/src/api/client.ts +4 -6
  21. package/src/audit/audit.logger.ts +19 -10
  22. package/src/client/components/ProtectedRoute.tsx +15 -11
  23. package/src/client/hooks/useAuth.ts +23 -21
  24. package/src/client/hooks/useConnectedAccounts.ts +57 -45
  25. package/src/client/hooks/usePermissions.ts +1 -1
  26. package/src/client/hooks/useRBAC.ts +6 -6
  27. package/src/client/hooks/useSession.ts +5 -5
  28. package/src/client/providers/AuthProvider.tsx +23 -17
  29. package/src/client/store/auth.store.ts +71 -62
  30. package/src/client/utils/storage.ts +45 -18
  31. package/src/common/constants/oauth-providers.ts +10 -7
  32. package/src/common/errors/auth.errors.ts +4 -4
  33. package/src/common/errors/specific-auth-errors.ts +5 -9
  34. package/src/common/regex/index.ts +6 -4
  35. package/src/common/types/auth.types.ts +47 -38
  36. package/src/common/types/index.ts +12 -6
  37. package/src/common/utils/index.ts +15 -11
  38. package/src/core/blacklist/token.blacklist.ts +13 -7
  39. package/src/core/index.ts +2 -2
  40. package/src/core/jwt/jwt.manager.ts +47 -22
  41. package/src/core/session/session.manager.ts +17 -14
  42. package/src/db/repositories/connected-account.repository.ts +120 -78
  43. package/src/db/repositories/role.repository.ts +41 -26
  44. package/src/db/repositories/session.repository.ts +9 -10
  45. package/src/db/repositories/user.repository.ts +105 -91
  46. package/src/flows/index.ts +2 -2
  47. package/src/flows/sign-in.flow.ts +28 -14
  48. package/src/flows/sign-up.flow.ts +31 -20
  49. package/src/index.ts +36 -37
  50. package/src/libs/clerk.helper.ts +6 -7
  51. package/src/libs/supabase.helper.ts +79 -61
  52. package/src/libs/supabaseClient.ts +3 -3
  53. package/src/providers/base/auth-provider.interface.ts +13 -11
  54. package/src/providers/base/index.ts +1 -1
  55. package/src/providers/index.ts +1 -1
  56. package/src/providers/oauth/facebook.provider.ts +63 -39
  57. package/src/providers/oauth/github.provider.ts +14 -10
  58. package/src/providers/oauth/google.provider.ts +39 -28
  59. package/src/providers/oauth/index.ts +1 -1
  60. package/src/rbac/dynamic-roles.ts +88 -54
  61. package/src/rbac/index.ts +4 -4
  62. package/src/rbac/permission-checker.ts +147 -75
  63. package/src/rbac/role-hierarchy.ts +8 -8
  64. package/src/rbac/role.manager.ts +11 -8
  65. package/src/security/csrf/csrf.protection.ts +9 -7
  66. package/src/security/index.ts +2 -2
  67. package/src/security/rate-limiting/auth/auth.controller.ts +2 -4
  68. package/src/security/rate-limiting/auth/rate-limiting.interface.ts +26 -6
  69. package/src/security/rate-limiting/auth.module.ts +1 -2
  70. package/src/server/auth.module.ts +55 -52
  71. package/src/server/decorators/auth.decorator.ts +9 -11
  72. package/src/server/decorators/auth.decorators.ts +8 -9
  73. package/src/server/decorators/current-user.decorator.ts +6 -6
  74. package/src/server/decorators/permission.decorator.ts +17 -9
  75. package/src/server/guards/auth.guard.ts +21 -16
  76. package/src/server/guards/custom-throttler.guard.ts +4 -9
  77. package/src/server/guards/permissions.guard.ts +32 -23
  78. package/src/server/guards/roles.guard.ts +14 -12
  79. package/src/server/middleware/auth.middleware.ts +4 -4
  80. package/src/server/middleware/session.middleware.ts +4 -4
  81. package/src/server/services/account.service.ts +96 -48
  82. package/src/server/services/auth.service.ts +57 -28
  83. package/src/server/services/brute-force.service.ts +24 -19
  84. package/src/server/services/index.ts +1 -1
  85. package/src/server/services/rate-limiter.service.ts +9 -4
  86. package/src/server/services/session.service.ts +84 -48
  87. package/src/server/services/token.service.ts +71 -51
  88. package/src/session/cookie-store.ts +47 -34
  89. package/src/session/enhanced-session-manager.ts +69 -48
  90. package/src/session/index.ts +5 -5
  91. package/src/session/memory-store.ts +37 -30
  92. package/src/session/redis-store.ts +105 -72
  93. package/src/strategies/oauth.strategy.ts +10 -9
  94. package/src/strategies/traditional-auth.strategy.ts +41 -29
  95. package/src/tokens/index.ts +4 -4
  96. package/src/tokens/refresh-token-manager.ts +70 -55
  97. package/src/tokens/token-validator.ts +109 -53
  98. package/vitest.setup.d.ts +2 -2
  99. package/vitest.setup.ts +1 -1
@@ -2,30 +2,30 @@
2
2
  /**
3
3
  * @fileoverview Token validator for @plyaz/auth
4
4
  * @module @plyaz/auth/tokens/token-validator
5
- *
5
+ *
6
6
  * @description
7
7
  * Provides comprehensive JWT token validation including signature verification,
8
8
  * expiration checks, blacklist validation, and issuer/audience verification.
9
9
  * Used by guards and middleware to validate incoming authentication tokens.
10
- *
10
+ *
11
11
  * @example
12
12
  * ```typescript
13
13
  * import { TokenValidator } from '@plyaz/auth';
14
- *
14
+ *
15
15
  * const validator = new TokenValidator({
16
16
  * publicKey: 'your-public-key',
17
17
  * issuer: 'plyaz.com',
18
18
  * audience: 'plyaz-api'
19
19
  * });
20
- *
20
+ *
21
21
  * const payload = await validator.validateToken(token);
22
22
  * ```
23
23
  */
24
24
 
25
- import type { JwtPayload, Algorithm } from 'jsonwebtoken';
26
- import { verify } from 'jsonwebtoken';
27
- import { TokenBlacklist } from '../core/blacklist/token.blacklist';
28
- import { Buffer } from 'buffer';
25
+ import type { JwtPayload, Algorithm } from "jsonwebtoken";
26
+ import { verify } from "jsonwebtoken";
27
+ import { TokenBlacklist } from "../core/blacklist/token.blacklist";
28
+ import { Buffer } from "buffer";
29
29
 
30
30
  /**
31
31
  * Token validation configuration
@@ -58,7 +58,7 @@ export interface ValidatedTokenPayload extends JwtPayload {
58
58
  /** User permissions */
59
59
  permissions?: string[];
60
60
  /** Token type */
61
- type?: 'access' | 'refresh';
61
+ type?: "access" | "refresh";
62
62
  }
63
63
 
64
64
  /**
@@ -87,14 +87,17 @@ export class TokenValidator {
87
87
 
88
88
  constructor(config: TokenValidatorConfig) {
89
89
  this.config = {
90
- algorithm: 'RS256',
90
+ algorithm: "RS256",
91
91
  clockTolerance: 30,
92
92
  enableBlacklist: true,
93
- ...config
93
+ ...config,
94
94
  };
95
95
 
96
96
  if (this.config.enableBlacklist) {
97
- this.blacklist = new TokenBlacklist({ keyPrefix: 'token:', defaultTTL: 3600 });
97
+ this.blacklist = new TokenBlacklist({
98
+ keyPrefix: "token:",
99
+ defaultTTL: 3600,
100
+ });
98
101
  }
99
102
  }
100
103
 
@@ -106,13 +109,19 @@ export class TokenValidator {
106
109
  async validateToken(token: string): Promise<TokenValidationResult> {
107
110
  try {
108
111
  // Basic format check
109
- if (!token || typeof token !== 'string') {
110
- return this.createErrorResult('INVALID_FORMAT', 'Token format is invalid');
112
+ if (!token || typeof token !== "string") {
113
+ return this.createErrorResult(
114
+ "INVALID_FORMAT",
115
+ "Token format is invalid",
116
+ );
111
117
  }
112
118
 
113
119
  // Check if token is blacklisted
114
- if (this.blacklist && await this.blacklist.isBlacklisted(token)) {
115
- return this.createErrorResult('TOKEN_REVOKED', 'Token has been revoked');
120
+ if (this.blacklist && (await this.blacklist.isBlacklisted(token))) {
121
+ return this.createErrorResult(
122
+ "TOKEN_REVOKED",
123
+ "Token has been revoked",
124
+ );
116
125
  }
117
126
 
118
127
  // Verify JWT signature and claims
@@ -120,7 +129,7 @@ export class TokenValidator {
120
129
  issuer: this.config.issuer,
121
130
  audience: this.config.audience,
122
131
  algorithms: [this.config.algorithm as Algorithm],
123
- clockTolerance: this.config.clockTolerance
132
+ clockTolerance: this.config.clockTolerance,
124
133
  }) as ValidatedTokenPayload;
125
134
 
126
135
  // Additional payload validation
@@ -131,9 +140,8 @@ export class TokenValidator {
131
140
 
132
141
  return {
133
142
  valid: true,
134
- payload
143
+ payload,
135
144
  };
136
-
137
145
  } catch (error) {
138
146
  return this.handleVerificationError(error as Error);
139
147
  }
@@ -146,11 +154,18 @@ export class TokenValidator {
146
154
  */
147
155
  async validateAccessToken(token: string): Promise<TokenValidationResult> {
148
156
  const result = await this.validateToken(token);
149
-
150
- if (result.valid && result.payload?.type && result.payload.type !== 'access') {
151
- return this.createErrorResult('INVALID_TOKEN_TYPE', 'Expected access token');
157
+
158
+ if (
159
+ result.valid &&
160
+ result.payload?.type &&
161
+ result.payload.type !== "access"
162
+ ) {
163
+ return this.createErrorResult(
164
+ "INVALID_TOKEN_TYPE",
165
+ "Expected access token",
166
+ );
152
167
  }
153
-
168
+
154
169
  return result;
155
170
  }
156
171
 
@@ -161,11 +176,18 @@ export class TokenValidator {
161
176
  */
162
177
  async validateRefreshToken(token: string): Promise<TokenValidationResult> {
163
178
  const result = await this.validateToken(token);
164
-
165
- if (result.valid && result.payload?.type && result.payload.type !== 'refresh') {
166
- return this.createErrorResult('INVALID_TOKEN_TYPE', 'Expected refresh token');
179
+
180
+ if (
181
+ result.valid &&
182
+ result.payload?.type &&
183
+ result.payload.type !== "refresh"
184
+ ) {
185
+ return this.createErrorResult(
186
+ "INVALID_TOKEN_TYPE",
187
+ "Expected refresh token",
188
+ );
167
189
  }
168
-
190
+
169
191
  return result;
170
192
  }
171
193
 
@@ -176,12 +198,12 @@ export class TokenValidator {
176
198
  */
177
199
  extractPayload(token: string): ValidatedTokenPayload | null {
178
200
  try {
179
- const parts = token.split('.');
201
+ const parts = token.split(".");
180
202
  if (parts.length !== 3) {
181
203
  return null;
182
204
  }
183
205
 
184
- const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString());
206
+ const payload = JSON.parse(Buffer.from(parts[1], "base64").toString());
185
207
  return payload;
186
208
  } catch {
187
209
  return null;
@@ -195,7 +217,7 @@ export class TokenValidator {
195
217
  */
196
218
  isTokenExpired(token: string): boolean {
197
219
  const payload = this.extractPayload(token);
198
-
220
+
199
221
  if (!payload?.exp) {
200
222
  return true;
201
223
  }
@@ -211,7 +233,7 @@ export class TokenValidator {
211
233
  */
212
234
  getTokenExpiration(token: string): Date | null {
213
235
  const payload = this.extractPayload(token);
214
-
236
+
215
237
  if (!payload?.exp) {
216
238
  return null;
217
239
  }
@@ -226,14 +248,14 @@ export class TokenValidator {
226
248
  */
227
249
  getTimeUntilExpiration(token: string): number | null {
228
250
  const expiration = this.getTokenExpiration(token);
229
-
251
+
230
252
  if (!expiration) {
231
253
  return null;
232
254
  }
233
255
 
234
256
  const now = Date.now();
235
257
  const timeUntilExpiry = expiration.getTime() - now;
236
-
258
+
237
259
  return Math.max(0, Math.floor(timeUntilExpiry / 1000));
238
260
  }
239
261
 
@@ -243,28 +265,42 @@ export class TokenValidator {
243
265
  * @returns Error result if invalid, null if valid
244
266
  * @private
245
267
  */
246
- private validatePayload(payload: ValidatedTokenPayload): TokenValidationResult | null {
268
+ private validatePayload(
269
+ payload: ValidatedTokenPayload,
270
+ ): TokenValidationResult | null {
247
271
  // Check required claims
248
272
  if (!payload.sub) {
249
- return this.createErrorResult('MISSING_SUBJECT', 'Token missing subject claim');
273
+ return this.createErrorResult(
274
+ "MISSING_SUBJECT",
275
+ "Token missing subject claim",
276
+ );
250
277
  }
251
278
 
252
279
  if (!payload.iat) {
253
- return this.createErrorResult('MISSING_ISSUED_AT', 'Token missing issued at claim');
280
+ return this.createErrorResult(
281
+ "MISSING_ISSUED_AT",
282
+ "Token missing issued at claim",
283
+ );
254
284
  }
255
285
 
256
286
  if (!payload.exp) {
257
- return this.createErrorResult('MISSING_EXPIRATION', 'Token missing expiration claim');
287
+ return this.createErrorResult(
288
+ "MISSING_EXPIRATION",
289
+ "Token missing expiration claim",
290
+ );
258
291
  }
259
292
 
260
293
  // Validate issued at time (not in future)
261
294
  const now = Math.floor(Date.now() / 1000);
262
295
  if (payload.iat > now + this.config.clockTolerance) {
263
- return this.createErrorResult('TOKEN_NOT_YET_VALID', 'Token issued in the future');
296
+ return this.createErrorResult(
297
+ "TOKEN_NOT_YET_VALID",
298
+ "Token issued in the future",
299
+ );
264
300
  }
265
301
 
266
302
  // Additional custom validations can be added here
267
-
303
+
268
304
  return null;
269
305
  }
270
306
 
@@ -274,20 +310,36 @@ export class TokenValidator {
274
310
  * @returns Error result
275
311
  * @private
276
312
  */
277
- private handleVerificationError(error : Error): TokenValidationResult {
278
- if (error.name === 'TokenExpiredError') {
279
- return this.createErrorResult('TOKEN_EXPIRED', 'Token has expired', error);
313
+ private handleVerificationError(error: Error): TokenValidationResult {
314
+ if (error.name === "TokenExpiredError") {
315
+ return this.createErrorResult(
316
+ "TOKEN_EXPIRED",
317
+ "Token has expired",
318
+ error,
319
+ );
280
320
  }
281
-
282
- if (error.name === 'JsonWebTokenError') {
283
- return this.createErrorResult('INVALID_SIGNATURE', 'Token signature is invalid', error);
321
+
322
+ if (error.name === "JsonWebTokenError") {
323
+ return this.createErrorResult(
324
+ "INVALID_SIGNATURE",
325
+ "Token signature is invalid",
326
+ error,
327
+ );
284
328
  }
285
-
286
- if (error.name === 'NotBeforeError') {
287
- return this.createErrorResult('TOKEN_NOT_YET_VALID', 'Token not yet valid', error);
329
+
330
+ if (error.name === "NotBeforeError") {
331
+ return this.createErrorResult(
332
+ "TOKEN_NOT_YET_VALID",
333
+ "Token not yet valid",
334
+ error,
335
+ );
288
336
  }
289
337
 
290
- return this.createErrorResult('VALIDATION_FAILED', error.message ?? 'Token validation failed', error);
338
+ return this.createErrorResult(
339
+ "VALIDATION_FAILED",
340
+ error.message ?? "Token validation failed",
341
+ error,
342
+ );
291
343
  }
292
344
 
293
345
  /**
@@ -298,14 +350,18 @@ export class TokenValidator {
298
350
  * @returns Error result
299
351
  * @private
300
352
  */
301
- private createErrorResult(code: string, message: string, details?: unknown): TokenValidationResult {
353
+ private createErrorResult(
354
+ code: string,
355
+ message: string,
356
+ details?: unknown,
357
+ ): TokenValidationResult {
302
358
  return {
303
359
  valid: false,
304
360
  error: {
305
361
  code,
306
362
  message,
307
- details
308
- }
363
+ details,
364
+ },
309
365
  };
310
366
  }
311
- }
367
+ }
package/vitest.setup.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import '@plyaz/devtools/configs/vitest.setup';
2
- //# sourceMappingURL=vitest.setup.d.ts.map
1
+ import "@plyaz/devtools/configs/vitest.setup";
2
+ //# sourceMappingURL=vitest.setup.d.ts.map
package/vitest.setup.ts CHANGED
@@ -1 +1 @@
1
- import '@plyaz/devtools/configs/vitest.setup';
1
+ import "@plyaz/devtools/configs/vitest.setup";