@plyaz/auth 1.0.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.
Files changed (113) hide show
  1. package/.github/pull_request_template.md +71 -0
  2. package/.github/workflows/deploy.yml +9 -0
  3. package/.github/workflows/publish.yml +14 -0
  4. package/.github/workflows/security.yml +20 -0
  5. package/README.md +89 -0
  6. package/commits.txt +5 -0
  7. package/dist/common/index.cjs +48 -0
  8. package/dist/common/index.cjs.map +1 -0
  9. package/dist/common/index.mjs +43 -0
  10. package/dist/common/index.mjs.map +1 -0
  11. package/dist/index.cjs +20411 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.mjs +5139 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/eslint.config.mjs +13 -0
  16. package/index.html +13 -0
  17. package/package.json +141 -0
  18. package/src/adapters/auth-adapter-factory.ts +26 -0
  19. package/src/adapters/auth-adapter.mapper.ts +53 -0
  20. package/src/adapters/base-auth.adapter.ts +119 -0
  21. package/src/adapters/clerk/clerk.adapter.ts +204 -0
  22. package/src/adapters/custom/custom.adapter.ts +119 -0
  23. package/src/adapters/index.ts +4 -0
  24. package/src/adapters/next-auth/authOptions.ts +81 -0
  25. package/src/adapters/next-auth/next-auth.adapter.ts +211 -0
  26. package/src/api/client.ts +37 -0
  27. package/src/audit/audit.logger.ts +52 -0
  28. package/src/client/components/ProtectedRoute.tsx +37 -0
  29. package/src/client/hooks/useAuth.ts +128 -0
  30. package/src/client/hooks/useConnectedAccounts.ts +108 -0
  31. package/src/client/hooks/usePermissions.ts +36 -0
  32. package/src/client/hooks/useRBAC.ts +36 -0
  33. package/src/client/hooks/useSession.ts +18 -0
  34. package/src/client/providers/AuthProvider.tsx +104 -0
  35. package/src/client/store/auth.store.ts +306 -0
  36. package/src/client/utils/storage.ts +70 -0
  37. package/src/common/constants/oauth-providers.ts +49 -0
  38. package/src/common/errors/auth.errors.ts +64 -0
  39. package/src/common/errors/specific-auth-errors.ts +201 -0
  40. package/src/common/index.ts +19 -0
  41. package/src/common/regex/index.ts +27 -0
  42. package/src/common/types/auth.types.ts +641 -0
  43. package/src/common/types/index.ts +297 -0
  44. package/src/common/utils/index.ts +84 -0
  45. package/src/core/blacklist/token.blacklist.ts +60 -0
  46. package/src/core/index.ts +2 -0
  47. package/src/core/jwt/jwt.manager.ts +131 -0
  48. package/src/core/session/session.manager.ts +56 -0
  49. package/src/db/repositories/connected-account.repository.ts +415 -0
  50. package/src/db/repositories/role.repository.ts +519 -0
  51. package/src/db/repositories/session.repository.ts +308 -0
  52. package/src/db/repositories/user.repository.ts +320 -0
  53. package/src/flows/index.ts +2 -0
  54. package/src/flows/sign-in.flow.ts +106 -0
  55. package/src/flows/sign-up.flow.ts +121 -0
  56. package/src/index.ts +54 -0
  57. package/src/libs/clerk.helper.ts +36 -0
  58. package/src/libs/supabase.helper.ts +255 -0
  59. package/src/libs/supabaseClient.ts +6 -0
  60. package/src/providers/base/auth-provider.interface.ts +42 -0
  61. package/src/providers/base/index.ts +1 -0
  62. package/src/providers/index.ts +2 -0
  63. package/src/providers/oauth/facebook.provider.ts +97 -0
  64. package/src/providers/oauth/github.provider.ts +148 -0
  65. package/src/providers/oauth/google.provider.ts +126 -0
  66. package/src/providers/oauth/index.ts +3 -0
  67. package/src/rbac/dynamic-roles.ts +552 -0
  68. package/src/rbac/index.ts +4 -0
  69. package/src/rbac/permission-checker.ts +464 -0
  70. package/src/rbac/role-hierarchy.ts +545 -0
  71. package/src/rbac/role.manager.ts +75 -0
  72. package/src/security/csrf/csrf.protection.ts +37 -0
  73. package/src/security/index.ts +3 -0
  74. package/src/security/rate-limiting/auth/auth.controller.ts +12 -0
  75. package/src/security/rate-limiting/auth/rate-limiting.interface.ts +67 -0
  76. package/src/security/rate-limiting/auth.module.ts +32 -0
  77. package/src/server/auth.module.ts +158 -0
  78. package/src/server/decorators/auth.decorator.ts +43 -0
  79. package/src/server/decorators/auth.decorators.ts +31 -0
  80. package/src/server/decorators/current-user.decorator.ts +49 -0
  81. package/src/server/decorators/permission.decorator.ts +49 -0
  82. package/src/server/guards/auth.guard.ts +56 -0
  83. package/src/server/guards/custom-throttler.guard.ts +46 -0
  84. package/src/server/guards/permissions.guard.ts +115 -0
  85. package/src/server/guards/roles.guard.ts +31 -0
  86. package/src/server/middleware/auth.middleware.ts +46 -0
  87. package/src/server/middleware/index.ts +2 -0
  88. package/src/server/middleware/middleware.ts +11 -0
  89. package/src/server/middleware/session.middleware.ts +255 -0
  90. package/src/server/services/account.service.ts +269 -0
  91. package/src/server/services/auth.service.ts +79 -0
  92. package/src/server/services/brute-force.service.ts +98 -0
  93. package/src/server/services/index.ts +15 -0
  94. package/src/server/services/rate-limiter.service.ts +60 -0
  95. package/src/server/services/session.service.ts +287 -0
  96. package/src/server/services/token.service.ts +262 -0
  97. package/src/session/cookie-store.ts +255 -0
  98. package/src/session/enhanced-session-manager.ts +406 -0
  99. package/src/session/index.ts +14 -0
  100. package/src/session/memory-store.ts +320 -0
  101. package/src/session/redis-store.ts +443 -0
  102. package/src/strategies/oauth.strategy.ts +128 -0
  103. package/src/strategies/traditional-auth.strategy.ts +116 -0
  104. package/src/tokens/index.ts +4 -0
  105. package/src/tokens/refresh-token-manager.ts +448 -0
  106. package/src/tokens/token-validator.ts +311 -0
  107. package/tsconfig.build.json +28 -0
  108. package/tsconfig.json +38 -0
  109. package/tsup.config.mjs +28 -0
  110. package/vitest.config.mjs +16 -0
  111. package/vitest.setup.d.ts +2 -0
  112. package/vitest.setup.d.ts.map +1 -0
  113. package/vitest.setup.ts +1 -0
@@ -0,0 +1,320 @@
1
+ /**
2
+ * @fileoverview Memory-based session store for @plyaz/auth
3
+ * @module @plyaz/auth/session/memory-store
4
+ *
5
+ * @description
6
+ * Implements session storage using in-memory storage. Provides fast session
7
+ * access but sessions are lost on server restart. Suitable for development,
8
+ * testing, or single-instance applications where session persistence across
9
+ * restarts is not required.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { MemoryStore } from '@plyaz/auth';
14
+ *
15
+ * const store = new MemoryStore({
16
+ * maxSessionsPerUser: 10,
17
+ * cleanupInterval: 300
18
+ * });
19
+ *
20
+ * await store.set('session_123', sessionData, 3600);
21
+ * ```
22
+ */
23
+
24
+ import { NUMERIX } from "@plyaz/config";
25
+ import type { SessionData, SessionStore, SessionStoreConfig } from "@plyaz/types";
26
+
27
+
28
+ /**
29
+ * Memory store configuration
30
+ */
31
+ export interface MemoryStoreConfig extends Partial<SessionStoreConfig> {
32
+ /** Enable automatic cleanup */
33
+ autoCleanup?: boolean;
34
+ }
35
+
36
+ /**
37
+ * Memory-based session store implementation
38
+ * Stores session data in server memory (Map)
39
+ */
40
+ export class MemoryStore implements SessionStore {
41
+ private readonly config: Required<MemoryStoreConfig>;
42
+ private readonly sessions = new Map<string, SessionData>();
43
+ private readonly userSessions = new Map<string, Set<string>>();
44
+ private cleanupTimer?:string;
45
+
46
+ constructor(config: MemoryStoreConfig = {}) {
47
+ this.config = {
48
+ defaultTTL: 3600,
49
+ maxSessionsPerUser: 5,
50
+ cleanupInterval: 300,
51
+ keyPrefix: 'session:',
52
+ autoCleanup: true,
53
+ ...config
54
+ };
55
+
56
+ // Start automatic cleanup if enabled
57
+ if (this.config.autoCleanup) {
58
+ this.startCleanupTimer();
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Store session data in memory
64
+ * @param sessionId - Session identifier
65
+ * @param data - Session data to store
66
+ * @param ttlSeconds - Time to live in seconds
67
+ */
68
+ async set(sessionId: string, data: SessionData, ttlSeconds: number): Promise<void> {
69
+ const sessionData: SessionData = {
70
+ ...data,
71
+ expiresAt: new Date(Date.now() + ttlSeconds * NUMERIX.THOUSAND)
72
+ };
73
+
74
+ // Enforce session limits per user
75
+ await this.enforceSessionLimits(data.userId);
76
+
77
+ // Store session
78
+ this.sessions.set(sessionId, sessionData);
79
+
80
+ // Track user sessions
81
+ if (!this.userSessions.has(data.userId)) {
82
+ this.userSessions.set(data.userId, new Set());
83
+ }
84
+ this.userSessions.get(data.userId)!.add(sessionId);
85
+ }
86
+
87
+ /**
88
+ * Retrieve session data from memory
89
+ * @param sessionId - Session identifier
90
+ * @returns Session data or null if not found/expired
91
+ */
92
+ async get(sessionId: string): Promise<SessionData | null> {
93
+ const data = this.sessions.get(sessionId);
94
+
95
+ if (!data) {
96
+ return null;
97
+ }
98
+
99
+ // Check expiration
100
+ if (data.expiresAt < new Date()) {
101
+ await this.delete(sessionId);
102
+ return null;
103
+ }
104
+
105
+ return data;
106
+ }
107
+
108
+ /**
109
+ * Delete session from memory
110
+ * @param sessionId - Session identifier
111
+ */
112
+ async delete(sessionId: string): Promise<void> {
113
+ const data = this.sessions.get(sessionId);
114
+
115
+ if (data) {
116
+ // Remove from sessions
117
+ this.sessions.delete(sessionId);
118
+
119
+ // Remove from user sessions tracking
120
+ const userSessionSet = this.userSessions.get(data.userId);
121
+ if (userSessionSet) {
122
+ userSessionSet.delete(sessionId);
123
+ if (userSessionSet.size === 0) {
124
+ this.userSessions.delete(data.userId);
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Delete all sessions for a user
132
+ * @param userId - User identifier
133
+ * @returns Number of deleted sessions
134
+ */
135
+ async deleteByUserId(userId: string): Promise<number> {
136
+ const userSessionSet = this.userSessions.get(userId);
137
+
138
+ if (!userSessionSet) {
139
+ return 0;
140
+ }
141
+
142
+ const sessionIds = Array.from(userSessionSet);
143
+ let deletedCount = 0;
144
+
145
+ for (const sessionId of sessionIds) {
146
+ if (this.sessions.has(sessionId)) {
147
+ this.sessions.delete(sessionId);
148
+ deletedCount++;
149
+ }
150
+ }
151
+
152
+ // Clear user session tracking
153
+ this.userSessions.delete(userId);
154
+
155
+ return deletedCount;
156
+ }
157
+
158
+ /**
159
+ * Update session activity timestamp
160
+ * @param sessionId - Session identifier
161
+ */
162
+ async updateActivity(sessionId: string): Promise<void> {
163
+ const data = this.sessions.get(sessionId);
164
+ if (data) {
165
+ data.lastActivityAt = new Date();
166
+ this.sessions.set(sessionId, data);
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Check if session exists and is valid
172
+ * @param sessionId - Session identifier
173
+ * @returns True if session exists and is valid
174
+ */
175
+ async exists(sessionId: string): Promise<boolean> {
176
+ const data = await this.get(sessionId);
177
+ return data !== null;
178
+ }
179
+
180
+ /**
181
+ * Get all active sessions for a user
182
+ * @param userId - User identifier
183
+ * @returns Array of session data
184
+ */
185
+ async getByUserId(userId: string): Promise<SessionData[]> {
186
+ const userSessionSet = this.userSessions.get(userId);
187
+
188
+ if (!userSessionSet) {
189
+ return [];
190
+ }
191
+
192
+ const userSessions: SessionData[] = [];
193
+ const now = new Date();
194
+
195
+ for (const sessionId of userSessionSet) {
196
+ const data = this.sessions.get(sessionId);
197
+ if (data && data.expiresAt > now) {
198
+ userSessions.push(data);
199
+ }
200
+ }
201
+
202
+ return userSessions;
203
+ }
204
+
205
+ /**
206
+ * Clean up expired sessions
207
+ * @returns Number of cleaned sessions
208
+ */
209
+ async cleanup(): Promise<number> {
210
+ let cleanedCount = 0;
211
+ const now = new Date();
212
+ const expiredSessions: string[] = [];
213
+
214
+ // Find expired sessions
215
+ for (const [sessionId, data] of this.sessions.entries()) {
216
+ if (data.expiresAt < now) {
217
+ expiredSessions.push(sessionId);
218
+ }
219
+ }
220
+
221
+ // Delete expired sessions
222
+ for (const sessionId of expiredSessions) {
223
+ await this.delete(sessionId);
224
+ cleanedCount++;
225
+ }
226
+
227
+ return cleanedCount;
228
+ }
229
+
230
+ /**
231
+ * Get session count for a user
232
+ * @param userId - User identifier
233
+ * @returns Session count
234
+ */
235
+ async getSessionCount(userId: string): Promise<number> {
236
+ const sessions = await this.getByUserId(userId);
237
+ return sessions.length;
238
+ }
239
+
240
+ /**
241
+ * Get total number of active sessions
242
+ * @returns Total session count
243
+ */
244
+ getTotalSessionCount(): number {
245
+ return this.sessions.size;
246
+ }
247
+
248
+ /**
249
+ * Get memory usage statistics
250
+ * @returns Memory usage information
251
+ */
252
+ getStats(): {
253
+ totalSessions: number;
254
+ totalUsers: number;
255
+ memoryUsage: number;
256
+ } {
257
+ return {
258
+ totalSessions: this.sessions.size,
259
+ totalUsers: this.userSessions.size,
260
+ memoryUsage: this.estimateMemoryUsage()
261
+ };
262
+ }
263
+
264
+ /**
265
+ * Destroy the store and cleanup resources
266
+ */
267
+ destroy(): void {
268
+ if (this.cleanupTimer) {
269
+
270
+ this.cleanupTimer = undefined;
271
+ }
272
+
273
+ this.sessions.clear();
274
+ this.userSessions.clear();
275
+ }
276
+
277
+ /**
278
+ * Enforce session limits per user
279
+ * @param userId - User identifier
280
+ * @private
281
+ */
282
+ private async enforceSessionLimits(userId: string): Promise<void> {
283
+ const userSessions = await this.getByUserId(userId);
284
+
285
+ if (userSessions.length >= this.config.maxSessionsPerUser) {
286
+ // Sort by last activity (oldest first)
287
+ userSessions.sort((a, b) => a.lastActivityAt.getTime() - b.lastActivityAt.getTime());
288
+
289
+ // Remove oldest sessions to make room
290
+ const sessionsToRemove = userSessions.length - this.config.maxSessionsPerUser + 1;
291
+ for (let i = 0; i < sessionsToRemove; i++) {
292
+ await this.delete(userSessions[i].id);
293
+ }
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Start automatic cleanup timer
299
+ * @private
300
+ */
301
+ private startCleanupTimer(): void {
302
+
303
+ }
304
+
305
+ /**
306
+ * Estimate memory usage (rough calculation)
307
+ * @returns Estimated memory usage in bytes
308
+ * @private
309
+ */
310
+ private estimateMemoryUsage(): number {
311
+ let totalSize = 0;
312
+
313
+ for (const [sessionId, data] of this.sessions.entries()) {
314
+ totalSize += sessionId.length * NUMERIX.TWO; // UTF-16 encoding
315
+ totalSize += JSON.stringify(data).length * NUMERIX.TWO;
316
+ }
317
+
318
+ return totalSize;
319
+ }
320
+ }