@warlock.js/auth 4.0.171 → 4.1.1

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 (164) hide show
  1. package/README.md +37 -0
  2. package/cjs/index.cjs +807 -0
  3. package/cjs/index.cjs.map +1 -0
  4. package/esm/commands/auth-cleanup-command.d.mts +13 -0
  5. package/esm/commands/auth-cleanup-command.d.mts.map +1 -0
  6. package/esm/commands/auth-cleanup-command.mjs +34 -0
  7. package/esm/commands/auth-cleanup-command.mjs.map +1 -0
  8. package/esm/commands/jwt-secret-generator-command.d.mts +5 -0
  9. package/esm/commands/jwt-secret-generator-command.d.mts.map +1 -0
  10. package/esm/commands/jwt-secret-generator-command.mjs +15 -0
  11. package/esm/commands/jwt-secret-generator-command.mjs.map +1 -0
  12. package/esm/contracts/auth-contract.d.mts +40 -0
  13. package/esm/contracts/auth-contract.d.mts.map +1 -0
  14. package/esm/contracts/index.d.mts +2 -0
  15. package/esm/contracts/types.d.mts +170 -0
  16. package/esm/contracts/types.d.mts.map +1 -0
  17. package/esm/contracts/types.mjs +25 -0
  18. package/esm/contracts/types.mjs.map +1 -0
  19. package/esm/index.d.mts +15 -0
  20. package/esm/index.mjs +17 -0
  21. package/esm/middleware/auth.middleware.d.mts +22 -0
  22. package/esm/middleware/auth.middleware.d.mts.map +1 -0
  23. package/esm/middleware/auth.middleware.mjs +72 -0
  24. package/esm/middleware/auth.middleware.mjs.map +1 -0
  25. package/esm/middleware/index.mjs +3 -0
  26. package/esm/models/access-token/access-token.model.d.mts +13 -0
  27. package/esm/models/access-token/access-token.model.d.mts.map +1 -0
  28. package/esm/models/access-token/access-token.model.mjs +23 -0
  29. package/esm/models/access-token/access-token.model.mjs.map +1 -0
  30. package/esm/models/access-token/index.d.mts +1 -0
  31. package/esm/models/access-token/index.mjs +3 -0
  32. package/esm/models/access-token/migration.mjs +24 -0
  33. package/esm/models/access-token/migration.mjs.map +1 -0
  34. package/esm/models/auth.model.d.mts +63 -0
  35. package/esm/models/auth.model.d.mts.map +1 -0
  36. package/esm/models/auth.model.mjs +77 -0
  37. package/esm/models/auth.model.mjs.map +1 -0
  38. package/esm/models/index.d.mts +8 -0
  39. package/esm/models/index.d.mts.map +1 -0
  40. package/esm/models/index.mjs +14 -0
  41. package/esm/models/index.mjs.map +1 -0
  42. package/esm/models/refresh-token/index.d.mts +1 -0
  43. package/esm/models/refresh-token/index.mjs +3 -0
  44. package/esm/models/refresh-token/migration.mjs +27 -0
  45. package/esm/models/refresh-token/migration.mjs.map +1 -0
  46. package/esm/models/refresh-token/refresh-token.model.d.mts +36 -0
  47. package/esm/models/refresh-token/refresh-token.model.d.mts.map +1 -0
  48. package/esm/models/refresh-token/refresh-token.model.mjs +58 -0
  49. package/esm/models/refresh-token/refresh-token.model.mjs.map +1 -0
  50. package/esm/services/auth-events.d.mts +89 -0
  51. package/esm/services/auth-events.d.mts.map +1 -0
  52. package/esm/services/auth-events.mjs +68 -0
  53. package/esm/services/auth-events.mjs.map +1 -0
  54. package/esm/services/auth.service.d.mts +95 -0
  55. package/esm/services/auth.service.d.mts.map +1 -0
  56. package/esm/services/auth.service.mjs +275 -0
  57. package/esm/services/auth.service.mjs.map +1 -0
  58. package/esm/services/generate-jwt-secret.d.mts +5 -0
  59. package/esm/services/generate-jwt-secret.d.mts.map +1 -0
  60. package/esm/services/generate-jwt-secret.mjs +48 -0
  61. package/esm/services/generate-jwt-secret.mjs.map +1 -0
  62. package/esm/services/index.d.mts +4 -0
  63. package/esm/services/index.mjs +6 -0
  64. package/esm/services/jwt.d.mts +52 -0
  65. package/esm/services/jwt.d.mts.map +1 -0
  66. package/esm/services/jwt.mjs +58 -0
  67. package/esm/services/jwt.mjs.map +1 -0
  68. package/esm/utils/auth-error-codes.d.mts +23 -0
  69. package/esm/utils/auth-error-codes.d.mts.map +1 -0
  70. package/esm/utils/auth-error-codes.mjs +23 -0
  71. package/esm/utils/auth-error-codes.mjs.map +1 -0
  72. package/llms-full.txt +1023 -0
  73. package/llms.txt +16 -0
  74. package/package.json +47 -36
  75. package/skills/auth-basics/SKILL.md +88 -0
  76. package/skills/customize-user-type/SKILL.md +137 -0
  77. package/skills/handle-login-and-logout/SKILL.md +160 -0
  78. package/skills/manage-tokens/SKILL.md +169 -0
  79. package/skills/overview/SKILL.md +66 -0
  80. package/skills/protect-routes/SKILL.md +105 -0
  81. package/skills/register-user/SKILL.md +135 -0
  82. package/skills/run-auth-commands/SKILL.md +125 -0
  83. package/esm/commands/auth-cleanup-command.d.ts +0 -10
  84. package/esm/commands/auth-cleanup-command.d.ts.map +0 -1
  85. package/esm/commands/auth-cleanup-command.js +0 -29
  86. package/esm/commands/auth-cleanup-command.js.map +0 -1
  87. package/esm/commands/jwt-secret-generator-command.d.ts +0 -2
  88. package/esm/commands/jwt-secret-generator-command.d.ts.map +0 -1
  89. package/esm/commands/jwt-secret-generator-command.js +0 -7
  90. package/esm/commands/jwt-secret-generator-command.js.map +0 -1
  91. package/esm/contracts/auth-contract.d.ts +0 -23
  92. package/esm/contracts/auth-contract.d.ts.map +0 -1
  93. package/esm/contracts/index.d.ts +0 -3
  94. package/esm/contracts/index.d.ts.map +0 -1
  95. package/esm/contracts/types.d.ts +0 -167
  96. package/esm/contracts/types.d.ts.map +0 -1
  97. package/esm/contracts/types.js +0 -20
  98. package/esm/contracts/types.js.map +0 -1
  99. package/esm/index.d.ts +0 -8
  100. package/esm/index.d.ts.map +0 -1
  101. package/esm/index.js +0 -1
  102. package/esm/index.js.map +0 -1
  103. package/esm/middleware/auth.middleware.d.ts +0 -2
  104. package/esm/middleware/auth.middleware.d.ts.map +0 -1
  105. package/esm/middleware/auth.middleware.js +0 -72
  106. package/esm/middleware/auth.middleware.js.map +0 -1
  107. package/esm/middleware/index.d.ts +0 -2
  108. package/esm/middleware/index.d.ts.map +0 -1
  109. package/esm/models/access-token/access-token.model.d.ts +0 -9
  110. package/esm/models/access-token/access-token.model.d.ts.map +0 -1
  111. package/esm/models/access-token/access-token.model.js +0 -14
  112. package/esm/models/access-token/access-token.model.js.map +0 -1
  113. package/esm/models/access-token/index.d.ts +0 -2
  114. package/esm/models/access-token/index.d.ts.map +0 -1
  115. package/esm/models/access-token/migration.d.ts +0 -2
  116. package/esm/models/access-token/migration.d.ts.map +0 -1
  117. package/esm/models/access-token/migration.js +0 -22
  118. package/esm/models/access-token/migration.js.map +0 -1
  119. package/esm/models/auth.model.d.ts +0 -58
  120. package/esm/models/auth.model.d.ts.map +0 -1
  121. package/esm/models/auth.model.js +0 -68
  122. package/esm/models/auth.model.js.map +0 -1
  123. package/esm/models/index.d.ts +0 -5
  124. package/esm/models/index.d.ts.map +0 -1
  125. package/esm/models/index.js +0 -1
  126. package/esm/models/index.js.map +0 -1
  127. package/esm/models/refresh-token/index.d.ts +0 -2
  128. package/esm/models/refresh-token/index.d.ts.map +0 -1
  129. package/esm/models/refresh-token/migration.d.ts +0 -2
  130. package/esm/models/refresh-token/migration.d.ts.map +0 -1
  131. package/esm/models/refresh-token/migration.js +0 -23
  132. package/esm/models/refresh-token/migration.js.map +0 -1
  133. package/esm/models/refresh-token/refresh-token.model.d.ts +0 -32
  134. package/esm/models/refresh-token/refresh-token.model.d.ts.map +0 -1
  135. package/esm/models/refresh-token/refresh-token.model.js +0 -53
  136. package/esm/models/refresh-token/refresh-token.model.js.map +0 -1
  137. package/esm/services/auth-events.d.ts +0 -85
  138. package/esm/services/auth-events.d.ts.map +0 -1
  139. package/esm/services/auth-events.js +0 -65
  140. package/esm/services/auth-events.js.map +0 -1
  141. package/esm/services/auth.service.d.ts +0 -92
  142. package/esm/services/auth.service.d.ts.map +0 -1
  143. package/esm/services/auth.service.js +0 -322
  144. package/esm/services/auth.service.js.map +0 -1
  145. package/esm/services/generate-jwt-secret.d.ts +0 -2
  146. package/esm/services/generate-jwt-secret.d.ts.map +0 -1
  147. package/esm/services/generate-jwt-secret.js +0 -47
  148. package/esm/services/generate-jwt-secret.js.map +0 -1
  149. package/esm/services/index.d.ts +0 -5
  150. package/esm/services/index.d.ts.map +0 -1
  151. package/esm/services/jwt.d.ts +0 -23
  152. package/esm/services/jwt.d.ts.map +0 -1
  153. package/esm/services/jwt.js +0 -40
  154. package/esm/services/jwt.js.map +0 -1
  155. package/esm/utils/auth-error-codes.d.ts +0 -18
  156. package/esm/utils/auth-error-codes.d.ts.map +0 -1
  157. package/esm/utils/auth-error-codes.js +0 -18
  158. package/esm/utils/auth-error-codes.js.map +0 -1
  159. package/esm/utils/duration.d.ts +0 -45
  160. package/esm/utils/duration.d.ts.map +0 -1
  161. package/esm/utils/duration.js +0 -93
  162. package/esm/utils/duration.js.map +0 -1
  163. package/esm/utils/index.d.ts +0 -3
  164. package/esm/utils/index.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["v","Model","v","Model","events","config","config","Random","colors","Random","config","Model"],"sources":["../../../../../@warlock.js/auth/src/models/access-token/access-token.model.ts","../../../../../@warlock.js/auth/src/models/refresh-token/refresh-token.model.ts","../../../../../@warlock.js/auth/src/services/auth-events.ts","../../../../../@warlock.js/auth/src/services/jwt.ts","../../../../../@warlock.js/auth/src/services/auth.service.ts","../../../../../@warlock.js/auth/src/commands/auth-cleanup-command.ts","../../../../../@warlock.js/auth/src/services/generate-jwt-secret.ts","../../../../../@warlock.js/auth/src/commands/jwt-secret-generator-command.ts","../../../../../@warlock.js/auth/src/contracts/types.ts","../../../../../@warlock.js/auth/src/utils/auth-error-codes.ts","../../../../../@warlock.js/auth/src/middleware/auth.middleware.ts","../../../../../@warlock.js/auth/src/models/access-token/migration.ts","../../../../../@warlock.js/auth/src/models/refresh-token/migration.ts","../../../../../@warlock.js/auth/src/models/auth.model.ts","../../../../../@warlock.js/auth/src/models/index.ts"],"sourcesContent":["import { Model } from \"@warlock.js/cascade\";\r\nimport { v } from \"@warlock.js/seal\";\r\n\r\nconst accessTokenSchema = v.object({\r\n token: v.string().required(),\r\n last_access: v.date().defaultNow().optional(),\r\n user_id: v.scalar().required(),\r\n user_type: v.string().required(),\r\n is_active: v.boolean().default(true),\r\n});\r\n\r\nexport class AccessToken extends Model {\r\n /**\r\n * {@inheritDoc}\r\n */\r\n public static table = \"access_tokens\";\r\n\r\n public static schema = accessTokenSchema;\r\n}\r\n","import { Model } from \"@warlock.js/cascade\";\nimport { v } from \"@warlock.js/seal\";\n\nconst refreshTokenSchema = v.object({\n token: v.string().required(),\n user_id: v.scalar().required(),\n user_type: v.string().required(),\n family_id: v.string().required(),\n expires_at: v.date().required(),\n last_used_at: v.date().default(() => new Date()),\n revoked_at: v.date().optional(),\n device_info: v.record(v.any()).optional(),\n});\n\nexport class RefreshToken extends Model {\n /**\n * {@inheritDoc}\n */\n public static table = \"refresh_tokens\";\n\n /**\n * {@inheritDoc}\n */\n public static schema = refreshTokenSchema;\n\n /**\n * Check if token is expired\n */\n public get isExpired(): boolean {\n const expiresAt = this.get(\"expires_at\");\n if (!expiresAt) return false;\n return new Date() > new Date(expiresAt);\n }\n\n /**\n * Check if token is revoked\n */\n public get isRevoked(): boolean {\n return !!this.get(\"revoked_at\");\n }\n\n /**\n * Check if token is valid (not expired and not revoked)\n */\n public get isValid(): boolean {\n return !this.isExpired && !this.isRevoked;\n }\n\n /**\n * Revoke this token\n */\n public async revoke(): Promise<this> {\n return this.merge({ revoked_at: new Date() }).save();\n }\n\n /**\n * Mark token as used (update last_used_at)\n */\n public async markAsUsed(): Promise<void> {\n await this.merge({ last_used_at: new Date() }).save();\n }\n}\n","import events, { type EventSubscription } from \"@mongez/events\";\nimport type { DeviceInfo, TokenPair } from \"../contracts/types\";\nimport type { Auth } from \"../models/auth.model\";\nimport type { RefreshToken } from \"../models/refresh-token\";\n\n/**\n * Auth event payload types\n */\nexport type AuthEventPayloads = {\n // Login events\n \"login.success\": [user: Auth, tokenPair: TokenPair, deviceInfo?: DeviceInfo];\n \"login.failed\": [credentials: { email?: string; username?: string }, reason: string];\n \"login.attempt\": [credentials: { email?: string; username?: string }];\n\n // Logout events\n logout: [user: Auth];\n \"logout.all\": [user: Auth];\n \"logout.failsafe\": [user: Auth];\n\n // Token events\n \"token.created\": [user: Auth, tokenPair: TokenPair];\n \"token.refreshed\": [user: Auth, newTokenPair: TokenPair, oldRefreshToken: RefreshToken];\n \"token.revoked\": [user: Auth, token: RefreshToken];\n \"token.expired\": [token: RefreshToken];\n \"token.familyRevoked\": [familyId: string, tokens: RefreshToken[]];\n\n // Password events\n \"password.changed\": [user: Auth];\n \"password.resetRequested\": [user: Auth, resetToken: string];\n \"password.reset\": [user: Auth];\n\n // Session events\n \"session.created\": [user: Auth, refreshToken: RefreshToken, deviceInfo?: DeviceInfo];\n \"session.destroyed\": [user: Auth, refreshToken: RefreshToken];\n\n // Cleanup events\n \"cleanup.completed\": [expiredCount: number];\n};\n\n/**\n * Auth event names\n */\nexport type AuthEventName = keyof AuthEventPayloads;\n\n/**\n * Callback type for a specific event\n */\nexport type AuthEventCallback<T extends AuthEventName> = (\n ...args: AuthEventPayloads[T]\n) => void | Promise<void>;\n\n/**\n * Event namespace prefix for auth events\n */\nconst AUTH_EVENT_PREFIX = \"auth.\";\n\n/**\n * Type-safe auth events manager\n *\n * @example\n * ```typescript\n * // Subscribe to events with full autocomplete\n * authEvents.on(\"login.success\", (user, tokenPair, deviceInfo) => {\n * console.log(`User ${user.id} logged in`);\n * });\n *\n * authEvents.on(\"token.refreshed\", (user, newPair, oldToken) => {\n * console.log(`Token refreshed for user ${user.id}`);\n * });\n *\n * // Trigger events\n * authEvents.emit(\"login.success\", user, tokenPair, deviceInfo);\n * ```\n */\nexport const authEvents = {\n /**\n * Subscribe to an auth event\n */\n on<T extends AuthEventName>(event: T, callback: AuthEventCallback<T>): EventSubscription {\n return events.subscribe(AUTH_EVENT_PREFIX + event, callback as Function);\n },\n\n /**\n * Subscribe to an auth event (alias for `on`)\n */\n subscribe<T extends AuthEventName>(event: T, callback: AuthEventCallback<T>): EventSubscription {\n return this.on(event, callback);\n },\n\n /**\n * Emit an auth event\n */\n emit<T extends AuthEventName>(event: T, ...args: AuthEventPayloads[T]): void {\n events.trigger(AUTH_EVENT_PREFIX + event, ...args);\n },\n\n /**\n * Emit an auth event (alias for `emit`)\n */\n trigger<T extends AuthEventName>(event: T, ...args: AuthEventPayloads[T]): void {\n this.emit(event, ...args);\n },\n\n /**\n * Unsubscribe from all auth events\n */\n unsubscribeAll(): void {\n events.unsubscribeNamespace(AUTH_EVENT_PREFIX.slice(0, -1));\n },\n\n /**\n * Unsubscribe from a specific auth event\n */\n off(event?: AuthEventName): void {\n if (event) {\n events.unsubscribe(AUTH_EVENT_PREFIX + event);\n } else {\n this.unsubscribeAll();\n }\n },\n};\n","import { config } from \"@warlock.js/core\";\r\nimport {\r\n createSigner,\r\n createVerifier,\r\n type Algorithm,\r\n type SignerOptions,\r\n type VerifierOptions,\r\n} from \"fast-jwt\";\r\nimport ms from \"ms\";\r\n\r\nconst getSecretKey = () => config.key(\"auth.jwt.secret\") as string;\r\nconst getAlgorithm = () => config.key(\"auth.jwt.algorithm\", \"HS256\") as Algorithm;\r\n\r\n// Refresh tokens may declare their own secret. When `auth.jwt.refresh.secret`\r\n// is unset/empty we fall back to the main JWT secret, matching the documented\r\n// optional behavior in `contracts/types.ts`.\r\nconst getRefreshSecretKey = () =>\r\n (config.key(\"auth.jwt.refresh.secret\") || getSecretKey()) as string;\r\n// Refresh token validity — defaults to 7d when not configured. Opt in to\r\n// no-expiry semantics with `NO_EXPIRATION` (100y) from `contracts/types.ts`.\r\nconst getRefreshTokenValidity = () => {\r\n const expiresIn = config.key(\"auth.jwt.refresh.expiresIn\") || \"7d\";\r\n\r\n return ms(expiresIn);\r\n};\r\n\r\nexport const jwt = {\r\n /**\r\n * Generate a new JWT token for the user.\r\n * @param payload The payload to encode in the JWT token.\r\n */\r\n async generate(\r\n payload: any,\r\n {\r\n key = getSecretKey(),\r\n algorithm = getAlgorithm(),\r\n ...options\r\n }: SignerOptions & { key?: string } = {},\r\n ): Promise<string> {\r\n // Create a signer function with predefined options\r\n const sign = createSigner({ key, ...options, algorithm });\r\n\r\n const token = await sign({ ...payload });\r\n return token;\r\n },\r\n\r\n /**\r\n * Verify the given token.\r\n * @param token The JWT token to verify.\r\n * @returns The decoded token payload if verification is successful.\r\n */\r\n async verify<T = any>(\r\n token: string,\r\n {\r\n key = getSecretKey(),\r\n algorithms = getAlgorithm() ? [getAlgorithm()] : undefined,\r\n ...options\r\n }: VerifierOptions & { key?: string } = {},\r\n ): Promise<T> {\r\n const verify = createVerifier({ key, ...options, algorithms });\r\n\r\n return await verify(token as string);\r\n },\r\n\r\n /**\r\n * Generate a new refresh token for the user.\r\n */\r\n async generateRefreshToken(\r\n payload: any,\r\n {\r\n key = getRefreshSecretKey(),\r\n expiresIn,\r\n algorithm = getAlgorithm(),\r\n ...options\r\n }: SignerOptions & { key?: string } = {},\r\n ): Promise<string> {\r\n const sign = createSigner({ key, expiresIn, algorithm, ...options });\r\n return sign({ ...payload });\r\n },\r\n\r\n /**\r\n * Verify the given refresh token.\r\n */\r\n async verifyRefreshToken<T = any>(\r\n token: string,\r\n {\r\n key = getRefreshSecretKey(),\r\n algorithms = [getAlgorithm()],\r\n ...options\r\n }: VerifierOptions & { key?: string } = {},\r\n ): Promise<T> {\r\n const verify = createVerifier({ key, algorithms, ...options });\r\n return await verify(token);\r\n },\r\n};\r\n","import { Random } from \"@mongez/reinforcements\";\nimport type { ChildModel } from \"@warlock.js/cascade\";\nimport { config, hashPassword, verifyPassword } from \"@warlock.js/core\";\nimport ms from \"ms\";\nimport type { AccessTokenOutput, DeviceInfo, LoginResult, TokenPair } from \"../contracts/types\";\nimport { AccessToken } from \"../models/access-token\";\nimport type { Auth } from \"../models/auth.model\";\nimport { RefreshToken } from \"../models/refresh-token\";\nimport { authEvents } from \"./auth-events\";\nimport { jwt } from \"./jwt\";\n\nclass AuthService {\n /**\n * Build access token payload from user\n */\n public buildAccessTokenPayload(user: Auth) {\n return {\n id: user.id,\n userType: user.userType,\n created_at: Date.now(),\n };\n }\n\n /**\n * Generate access token for user\n */\n public async generateAccessToken(user: Auth, payload?: any): Promise<AccessTokenOutput> {\n const data = payload || this.buildAccessTokenPayload(user);\n const expiresInConfig = config.key(\"auth.jwt.expiresIn\");\n const expiresIn = expiresInConfig ? ms(expiresInConfig) : 3_600; // default 1 hour\n\n // If expiresIn is undefined, token never expires\n const token = await jwt.generate(data, { expiresIn });\n\n const decoed = await jwt.verify(token);\n\n // Store in database\n await AccessToken.create({\n token,\n user_id: user.id,\n user_type: user.userType,\n });\n\n return { token, expiresAt: new Date(decoed.exp * 1_000).toISOString() };\n }\n\n /**\n * Create refresh token for user\n */\n public async createRefreshToken(\n user: Auth,\n deviceInfo?: DeviceInfo,\n ): Promise<RefreshToken | undefined> {\n if (config.get(\"auth.jwt.refresh.enabled\") === false) return;\n\n const familyId = deviceInfo?.familyId || Random.string(32);\n\n const payload = {\n userId: user.id,\n userType: user.userType,\n familyId,\n };\n\n const epireTime = config.get(\"auth.jwt.refresh.expiresIn\", \"7d\");\n\n const expiresIn = ms(epireTime);\n\n const token = await jwt.generateRefreshToken(payload, { expiresIn });\n\n // Calculate expiration date (undefined means never expires, but we still set a far future date)\n const expiresAt = new Date(Date.now() + expiresIn).toISOString();\n\n // Enforce max tokens per user\n await this.enforceMaxRefreshTokens(user);\n\n // Store in database\n return RefreshToken.create({\n token,\n user_id: user.id,\n user_type: user.userType,\n family_id: familyId,\n expires_at: expiresAt,\n device_info: deviceInfo\n ? {\n userAgent: deviceInfo.userAgent,\n ip: deviceInfo.ip,\n deviceId: deviceInfo.deviceId,\n }\n : undefined,\n });\n }\n\n /**\n * Create both access and refresh tokens\n */\n public async createTokenPair(user: Auth, deviceInfo?: DeviceInfo): Promise<TokenPair> {\n const accessToken = await this.generateAccessToken(user, deviceInfo?.payload);\n const refreshToken = await this.createRefreshToken(user, deviceInfo);\n\n const tokenPair: TokenPair = {\n accessToken,\n refreshToken: refreshToken\n ? {\n token: refreshToken.get(\"token\"),\n expiresAt: refreshToken.get(\"expires_at\"),\n }\n : undefined,\n };\n\n // Emit events\n authEvents.emit(\"token.created\", user, tokenPair);\n\n if (refreshToken) {\n authEvents.emit(\"session.created\", user, refreshToken, deviceInfo);\n }\n\n return tokenPair;\n }\n\n /**\n * Refresh tokens using a refresh token\n */\n public async refreshTokens(\n refreshTokenString: string,\n deviceInfo?: DeviceInfo,\n ): Promise<TokenPair | null> {\n try {\n // 1. Verify JWT signature\n const decoded = await jwt.verifyRefreshToken<{\n userId: number;\n userType: string;\n familyId: string;\n }>(refreshTokenString);\n\n if (!decoded) return null;\n\n // 2. Find token in database\n const refreshToken = await RefreshToken.first({ token: refreshTokenString });\n\n if (!refreshToken?.isValid) {\n // If token was already used (rotation detection), revoke entire family\n if (refreshToken) {\n await this.revokeTokenFamily(refreshToken.get(\"family_id\"));\n }\n return null;\n }\n\n // 3. Get user model and find user\n const UserModel = config.key(`auth.userType.${decoded.userType}`);\n if (!UserModel) return null;\n\n const user = (await UserModel.find(decoded.userId)) as Auth | null;\n if (!user) return null;\n\n // 4. Rotate token if enabled (revoke old token)\n const rotationEnabled = config.key(\"auth.jwt.refresh.rotation\", true);\n if (rotationEnabled) {\n await refreshToken.revoke();\n } else {\n await refreshToken.markAsUsed();\n }\n\n // 5. Generate new token pair (keep same family)\n const newTokenPair = await this.createTokenPair(user, {\n ...deviceInfo,\n familyId: refreshToken.get(\"family_id\"),\n });\n\n // Emit token refreshed event\n authEvents.emit(\"token.refreshed\", user, newTokenPair, refreshToken);\n\n return newTokenPair;\n } catch {\n return null;\n }\n }\n\n /**\n * Verify password\n */\n public async verifyPassword(plainPassword: string, hashedPassword: string): Promise<boolean> {\n return verifyPassword(plainPassword, hashedPassword);\n }\n\n /**\n * Hash password\n */\n public async hashPassword(password: string): Promise<string> {\n return hashPassword(password);\n }\n\n /**\n * Attempt to login user with given credentials\n */\n public async attemptLogin<T extends Auth>(Model: ChildModel<T>, data: any): Promise<T | null> {\n const { password, ...otherData } = data;\n\n // Emit login attempt event\n authEvents.emit(\"login.attempt\", otherData);\n\n const user = (await Model.first(otherData)) as T | null;\n\n if (!user) {\n authEvents.emit(\"login.failed\", otherData, \"User not found\");\n return null;\n }\n\n if (!(await this.verifyPassword(password, user.string(\"password\")!))) {\n authEvents.emit(\"login.failed\", otherData, \"Invalid password\");\n return null;\n }\n\n return user;\n }\n\n /**\n * Full login flow: validate credentials, create tokens, emit events\n * Returns token pair on success, null on failure\n */\n public async login<T extends Auth>(\n Model: ChildModel<T>,\n credentials: any,\n deviceInfo?: DeviceInfo,\n ): Promise<LoginResult<T> | null> {\n const user = await this.attemptLogin(Model, credentials);\n\n if (!user) {\n return null;\n }\n\n // if no refresh token in config, then return user and access token only\n if (!config.key(\"auth.jwt.refresh.enabled\", true)) {\n const accessToken = await this.generateAccessToken(user, deviceInfo?.payload);\n return { user, tokens: { accessToken } };\n }\n\n const tokens = await this.createTokenPair(user, deviceInfo);\n\n // Emit login success event\n authEvents.emit(\"login.success\", user, tokens, deviceInfo);\n\n return { user, tokens } as LoginResult<T>;\n }\n\n /**\n * Logout user\n * @param user - The authenticated user\n * @param accessToken - Optional access token string to revoke\n * @param refreshToken - Optional refresh token string to revoke\n * If refresh token is not provided, behavior is determined by config:\n * - \"revoke-all\" (default): Revoke ALL refresh tokens for security\n * - \"error\": Throw error requiring refresh token\n */\n public async logout(user: Auth, accessToken?: string, refreshToken?: string): Promise<void> {\n // Remove access token if provided\n if (accessToken) {\n await this.removeAccessToken(user, accessToken);\n }\n\n if (refreshToken) {\n // Revoke specific refresh token\n const token = await RefreshToken.first({\n token: refreshToken,\n userId: user.id, // Security: ensure token belongs to this user\n });\n\n if (token) {\n await token.revoke();\n authEvents.emit(\"session.destroyed\", user, token);\n }\n } else {\n // No refresh token provided - check configured behavior\n const behavior = config.key(\"auth.jwt.refresh.logoutWithoutToken\", \"revoke-all\") as\n | \"revoke-all\"\n | \"error\";\n\n if (behavior === \"error\") {\n throw new Error(\"Refresh token required for logout\");\n }\n\n // Default: revoke-all (fail-safe)\n await this.revokeAllTokens(user);\n authEvents.emit(\"logout.failsafe\", user);\n }\n\n // Emit logout event\n authEvents.emit(\"logout\", user);\n }\n\n /**\n * Remove specific access token\n */\n public async removeAccessToken(user: Auth, token: string): Promise<void> {\n AccessToken.delete({\n token,\n userId: user.id,\n });\n }\n\n /**\n * Remove all access tokens for a user\n */\n public async removeAllAccessTokens(user: Auth): Promise<void> {\n // Delete access token\n AccessToken.delete({\n user_id: user.id,\n });\n }\n\n /**\n * Remove specific refresh token\n */\n public async removeRefreshToken(user: Auth, token: string): Promise<void> {\n RefreshToken.delete({\n token,\n userId: user.id,\n });\n }\n\n /**\n * Revoke all tokens for a user\n */\n public async revokeAllTokens(user: Auth): Promise<void> {\n // Revoke all refresh tokens\n const refreshTokens = await RefreshToken.query()\n .where(\"user_id\", user.id)\n .where(\"user_type\", user.userType)\n .where(\"revoked_at\", null)\n .get();\n\n for (const token of refreshTokens) {\n await token.revoke();\n authEvents.emit(\"token.revoked\", user, token);\n }\n\n // Delete all access tokens\n await this.removeAllAccessTokens(user);\n\n // Emit logout all event\n authEvents.emit(\"logout.all\", user);\n }\n\n /**\n * Revoke entire token family (for rotation breach detection)\n */\n public async revokeTokenFamily(familyId: string): Promise<void> {\n const tokens = await RefreshToken.query()\n .where(\"family_id\", familyId)\n .where(\"revoked_at\", null)\n .get();\n\n for (const token of tokens) {\n await token.revoke();\n }\n\n // Emit family revoked event\n authEvents.emit(\"token.familyRevoked\", familyId, tokens);\n }\n\n /**\n * Cleanup expired tokens\n */\n public async cleanupExpiredTokens(): Promise<number> {\n const expiredTokens = await RefreshToken.query().where(\"expires_at\", \"<\", new Date()).get();\n\n for (const token of expiredTokens) {\n authEvents.emit(\"token.expired\", token);\n await token.destroy();\n }\n\n // Emit cleanup completed event\n authEvents.emit(\"cleanup.completed\", expiredTokens.length);\n\n return expiredTokens.length;\n }\n\n /**\n * Enforce max refresh tokens per user\n */\n private async enforceMaxRefreshTokens(user: Auth): Promise<void> {\n const maxPerUser = config.key(\"auth.jwt.refresh.maxPerUser\", 5);\n\n const activeTokens = await RefreshToken.query()\n .where({\n user_id: user.id,\n user_type: user.userType,\n revoked_at: null,\n })\n .orderBy(\"created_at\", \"asc\")\n .get();\n\n // Revoke oldest tokens if exceeding limit\n if (activeTokens.length >= maxPerUser) {\n const tokensToRevoke = activeTokens.slice(0, activeTokens.length - maxPerUser + 1);\n for (const token of tokensToRevoke) {\n await token.revoke();\n }\n }\n }\n\n /**\n * Get active sessions for user\n */\n public async getActiveSessions(user: Auth): Promise<RefreshToken[]> {\n return RefreshToken.query()\n .where({\n user_id: user.id,\n user_type: user.userType,\n revoked_at: null,\n })\n .where(\"expires_at\", \">\", new Date())\n .orderBy(\"created_at\", \"desc\")\n .get();\n }\n}\n\nexport const authService = new AuthService();\n","import { colors } from \"@mongez/copper\";\nimport { command } from \"@warlock.js/core\";\nimport { authService } from \"../services/auth.service\";\n\n/**\n * Register the auth:cleanup CLI command\n *\n * @example\n * ```bash\n * warlock auth:cleanup\n * ```\n */\nexport function registerAuthCleanupCommand() {\n return command({\n name: \"auth.cleanup\",\n description: \"Remove expired refresh tokens from the database\",\n preload: {\n env: true,\n config: [\"auth\", \"database\"],\n connectors: [\"database\"],\n },\n action: async () => {\n console.log(colors.cyan(\"🧹 Cleaning up expired tokens...\"));\n\n const count = await authService.cleanupExpiredTokens();\n\n if (count === 0) {\n console.log(colors.green(\"✅ No expired tokens found.\"));\n } else {\n console.log(colors.green(`✅ Removed ${count} expired token(s).`));\n }\n },\n });\n}\n","import { fileExistsAsync, getFileAsync, putFileAsync } from \"@warlock.js/fs\";\r\nimport { Random } from \"@mongez/reinforcements\";\r\nimport { environment, rootPath } from \"@warlock.js/core\";\r\nimport { log } from \"@warlock.js/logger\";\r\n\r\nexport async function generateJWTSecret() {\r\n let envFile = rootPath(\".env\");\r\n\r\n log.info(\"jwt\", \"generating\", \"Generating JWT secrets\");\r\n\r\n const environmentMode = environment();\r\n\r\n if (!(await fileExistsAsync(envFile))) {\r\n const envFileType = environmentMode === \"production\" ? \".env.production\" : \".env.development\";\r\n envFile = rootPath(envFileType);\r\n }\r\n\r\n if (!(await fileExistsAsync(envFile))) {\r\n log.error(\"jwt\", \"error\", \".env file not found\");\r\n return;\r\n }\r\n\r\n let contents = await getFileAsync(envFile);\r\n\r\n const hasJwtSecret = contents.includes(\"JWT_SECRET\");\r\n const hasJwtRefreshSecret = contents.includes(\"JWT_REFRESH_SECRET\");\r\n\r\n if (hasJwtSecret && hasJwtRefreshSecret) {\r\n log.warn(\"jwt\", \"exists\", \"JWT secrets already exist in the .env file.\");\r\n return;\r\n }\r\n\r\n let secretsToAdd = \"\";\r\n\r\n if (!hasJwtSecret) {\r\n const jwtSecret = Random.string(32);\r\n secretsToAdd += `\r\n# JWT Secret\r\nJWT_SECRET=${jwtSecret}\r\n`;\r\n log.success(\"jwt\", \"generated\", \"JWT_SECRET generated and added to the .env file.\");\r\n } else {\r\n log.info(\"jwt\", \"exists\", \"JWT_SECRET already exists in the .env file.\");\r\n }\r\n\r\n if (!hasJwtRefreshSecret) {\r\n const jwtRefreshSecret = Random.string(32);\r\n secretsToAdd += `\r\n# JWT Refresh Secret\r\nJWT_REFRESH_SECRET=${jwtRefreshSecret}\r\n`;\r\n log.success(\"jwt\", \"generated\", \"JWT_REFRESH_SECRET generated and added to the .env file.\");\r\n } else {\r\n log.info(\"jwt\", \"exists\", \"JWT_REFRESH_SECRET already exists in the .env file.\");\r\n }\r\n\r\n if (secretsToAdd) {\r\n contents += secretsToAdd;\r\n await putFileAsync(envFile, contents);\r\n }\r\n}\r\n","import { command } from \"@warlock.js/core\";\r\nimport { generateJWTSecret } from \"../services/generate-jwt-secret\";\r\n\r\nexport function registerJWTSecretGeneratorCommand() {\r\n return command({\r\n name: \"jwt.generate\",\r\n description: \"Generate JWT Secret key in .env file\",\r\n action: generateJWTSecret,\r\n });\r\n}\r\n","import { ChildModel } from \"@warlock.js/cascade\";\r\nimport { type Algorithm } from \"fast-jwt\";\r\nimport type { Auth } from \"../models/auth.model\";\r\n\r\n/**\r\n * Symbol to indicate no expiration for tokens\r\n * Use this when you explicitly want tokens to never expire\r\n *\r\n * @example\r\n * ```typescript\r\n * // src/config/auth.ts\r\n * import { NO_EXPIRATION, type AuthConfigurations } from \"@warlock.js/auth\";\r\n *\r\n * const authConfigurations: AuthConfigurations = {\r\n * jwt: {\r\n * secret: env(\"JWT_SECRET\"),\r\n * expiresIn: NO_EXPIRATION, // Token expires within 100 years\r\n * },\r\n * };\r\n *\r\n * export default authConfigurations;\r\n * ```\r\n */\r\nexport const NO_EXPIRATION = \"100y\";\r\n\r\n/**\r\n * Behavior when logout is called without a refresh token\r\n * - \"revoke-all\": Revoke all refresh tokens for the user (secure default)\r\n * - \"error\": Return an error requiring the refresh token\r\n */\r\nexport type LogoutWithoutTokenBehavior = \"revoke-all\" | \"error\";\r\n\r\nexport type AuthConfigurations = {\r\n /**\r\n * Define all user types\r\n * This is important to differentiate between user types when validating and generating tokens\r\n */\r\n userType: {\r\n [userType: string]: ChildModel<Auth>;\r\n };\r\n /**\r\n * JWT configurations\r\n */\r\n jwt: {\r\n /**\r\n * JWT secret key for signing access tokens\r\n */\r\n secret: string;\r\n /**\r\n * JWT algorithm\r\n * @default \"HS256\"\r\n */\r\n algorithm?: Algorithm;\r\n /**\r\n * Access token expiration time\r\n * It accepts any value `ms` package accepts\r\n * @example \"1h\" or NO_EXPIRATION\r\n * @default \"1h\"\r\n */\r\n expiresIn?: string;\r\n /**\r\n * Refresh token configurations\r\n */\r\n refresh?: {\r\n /**\r\n * Separate secret for refresh tokens (recommended for security)\r\n * If not provided, falls back to main JWT secret\r\n */\r\n secret?: string;\r\n /**\r\n * Enable refresh token\r\n * @default true\r\n */\r\n enabled?: boolean;\r\n /**\r\n * Refresh token expiration time\r\n * It accepts any value `ms` package accepts\r\n * @example \"7d\" or \"1w\"\r\n * @default \"7d\"\r\n */\r\n expiresIn?: string;\r\n /**\r\n * Enable token rotation (issue new refresh token on each use)\r\n * Old refresh token is invalidated after use\r\n * @default true\r\n */\r\n rotation?: boolean;\r\n /**\r\n * Maximum number of active refresh tokens per user\r\n * When exceeded, oldest tokens are revoked\r\n * @default 5\r\n */\r\n maxPerUser?: number;\r\n /**\r\n * Behavior when logout is called without a refresh token\r\n * - \"revoke-all\": Revoke all tokens for security (default)\r\n * - \"error\": Require refresh token, return error if missing\r\n * @default \"revoke-all\"\r\n */\r\n logoutWithoutToken?: LogoutWithoutTokenBehavior;\r\n };\r\n };\r\n /**\r\n * Password configurations\r\n */\r\n password?: {\r\n /**\r\n * Password salt\r\n * The higher the salt, the more secure the password is\r\n * But, it will take more time to generate the password\r\n * @default 12\r\n */\r\n salt?: number;\r\n };\r\n};\r\n\r\nexport type AccessTokenOutput = {\r\n /**\r\n * JWT Token\r\n */\r\n token: string;\r\n /**\r\n * Exprie time in ISO format UTC time\r\n */\r\n expiresAt: string;\r\n};\r\n\r\n/**\r\n * Token pair returned after login or token refresh\r\n */\r\nexport type TokenPair = {\r\n /**\r\n * JWT access token (short-lived)\r\n */\r\n accessToken: AccessTokenOutput;\r\n /**\r\n * JWT refresh token (long-lived)\r\n */\r\n refreshToken?: AccessTokenOutput;\r\n};\r\n\r\n/**\r\n * Device information for session tracking\r\n */\r\nexport type DeviceInfo = {\r\n /**\r\n * User agent string from request\r\n */\r\n userAgent?: string;\r\n /**\r\n * Client IP address\r\n */\r\n ip?: string;\r\n /**\r\n * Optional device identifier\r\n */\r\n deviceId?: string;\r\n /**\r\n * Token family ID (for rotation tracking)\r\n * @internal\r\n */\r\n familyId?: string;\r\n /**\r\n * Access token payload\r\n */\r\n payload?: Record<string, any>;\r\n};\r\n\r\nexport type LoginResult<UserType extends Auth> = {\r\n user: UserType;\r\n tokens: TokenPair;\r\n};\r\n","export enum AuthErrorCodes {\n /**\n * Missing Access Token Error Code EC001\n * EC001 = Missing Access Token\n */\n MissingAccessToken = \"EC001\", // Error Code 001\n /**\n * Invalid Access Token Error Code EC002\n * EC002 = Invalid Access Token\n */\n InvalidAccessToken = \"EC002\", // Error Code 002\n /**\n * Unauthorized Error Code EC003\n * EC003 = Unauthorized\n */\n Unauthorized = \"EC003\", // Error Code 003\n}\n","import { config, t, type Middleware, type Request, type Response } from \"@warlock.js/core\";\r\nimport { log } from \"@warlock.js/logger\";\r\nimport { AccessToken } from \"../models/access-token\";\r\nimport { jwt } from \"../services/jwt\";\r\nimport { AuthErrorCodes } from \"../utils/auth-error-codes\";\r\n\r\n/**\r\n * Build a route gate that always requires an authenticated request.\r\n *\r\n * The argument is mandatory and selects which user types may pass:\r\n * - `[]` — any authenticated user (token required, type not checked).\r\n * - `\"admin\"` / `[\"admin\", \"staff\"]` — token required AND the user's\r\n * `userType` must be one of the listed types.\r\n *\r\n * There is no anonymous/optional mode: a request without a valid access\r\n * token is always rejected with `401`. Routes that should be public\r\n * simply omit the middleware.\r\n *\r\n * @example\r\n * router.get(\"/account\", authMiddleware([]), accountController);\r\n * router.get(\"/admin\", authMiddleware(\"admin\"), adminController);\r\n * router.get(\"/back-office\", authMiddleware([\"admin\", \"staff\"]), backOfficeController);\r\n */\r\nexport function authMiddleware(allowedUserType: string | string[]) {\r\n const allowedTypes = Array.isArray(allowedUserType) ? allowedUserType : [allowedUserType];\r\n\r\n const auth: Middleware = async (request: Request, response: Response) => {\r\n try {\r\n const authorizationValue = request.authorizationValue;\r\n\r\n if (!authorizationValue) {\r\n return response.unauthorized({\r\n error: t(\"auth.errors.missingAccessToken\"),\r\n errorCode: AuthErrorCodes.MissingAccessToken,\r\n });\r\n }\r\n\r\n // get current user jwt\r\n const user = await jwt.verify(authorizationValue);\r\n\r\n // store decoded access token object in request object\r\n request.decodedAccessToken = user;\r\n // use our own jwt verify to verify the token\r\n const accessToken = await AccessToken.first({\r\n token: authorizationValue,\r\n });\r\n\r\n if (!accessToken) {\r\n return response.unauthorized({\r\n error: t(\"auth.errors.invalidAccessToken\"),\r\n errorCode: AuthErrorCodes.InvalidAccessToken,\r\n });\r\n }\r\n\r\n // now, we need to get an instance of user using its corresponding model\r\n const userType = user.userType || accessToken.get(\"userType\");\r\n\r\n // check if the user type is allowed\r\n if (allowedTypes.length && !allowedTypes.includes(userType)) {\r\n return response.unauthorized({\r\n error: t(\"auth.errors.unauthorized\"),\r\n errorCode: AuthErrorCodes.Unauthorized,\r\n });\r\n }\r\n\r\n // get user model class\r\n const UserModel = config.key(`auth.userType.${userType}`);\r\n\r\n if (!UserModel) {\r\n throw new Error(`User type ${userType} is unknown type.`);\r\n }\r\n\r\n // get user model instance\r\n const currentUser = await UserModel.find(user.id);\r\n\r\n if (!currentUser) {\r\n accessToken.destroy();\r\n return response.unauthorized({\r\n error: t(\"auth.errors.invalidAccessToken\"),\r\n errorCode: AuthErrorCodes.InvalidAccessToken,\r\n });\r\n }\r\n\r\n // update last access\r\n // accessToken.set(\"lastAccess\", new Date());\r\n // await accessToken.save({ skipEvents: true });\r\n\r\n // set current user\r\n request.user = currentUser;\r\n } catch (err: any) {\r\n log.error(\"http\", \"auth\", err);\r\n\r\n request.clearCurrentUser();\r\n\r\n return response.unauthorized({\r\n error: t(\"auth.errors.invalidAccessToken\"),\r\n errorCode: AuthErrorCodes.InvalidAccessToken,\r\n });\r\n }\r\n };\r\n\r\n return auth;\r\n}\r\n","import { migrate } from \"@warlock.js/cascade\";\r\nimport { AccessToken } from \"./access-token.model\";\r\n\r\nexport const AccessTokenMigration = migrate(AccessToken, {\r\n name: \"accessToken\",\r\n up() {\r\n // Create table\r\n this.createTableIfNotExists();\r\n\r\n // Primary key\r\n this.primaryUuid();\r\n\r\n // Token field\r\n this.text(\"token\").unique();\r\n this.timestamp(\"last_access\").nullable();\r\n\r\n // User reference (flat columns for cross-driver compatibility)\r\n this.uuid(\"user_id\").index();\r\n this.string(\"user_type\", 50).nullable();\r\n\r\n // Status (for token revocation)\r\n this.boolean(\"is_active\").nullable();\r\n\r\n // Timestamps\r\n this.timestamps();\r\n },\r\n down() {\r\n this.dropTableIfExists();\r\n },\r\n});\r\n","import { migrate } from \"@warlock.js/cascade\";\nimport { RefreshToken } from \"./refresh-token.model\";\n\nexport const RefreshTokenMigration = migrate(RefreshToken, {\n name: \"refreshToken\",\n up() {\n // Create table\n this.createTableIfNotExists();\n\n // Primary key\n this.primaryUuid();\n\n // Token fields\n this.text(\"token\").unique();\n this.uuid(\"user_id\").index();\n this.string(\"user_type\", 50).nullable();\n this.text(\"family_id\").index().nullable();\n this.timestamp(\"expires_at\").index().nullable();\n this.timestamp(\"last_used_at\").nullable();\n this.timestamp(\"revoked_at\").nullable();\n this.json(\"device_info\").nullable();\n\n // Timestamps\n this.timestamps();\n },\n down() {\n this.dropTableIfExists();\n },\n});\n","import { type ChildModel, Model, type ModelSchema } from \"@warlock.js/cascade\";\r\nimport type { Authenticable } from \"../contracts/auth-contract\";\r\nimport type { AccessTokenOutput, DeviceInfo, TokenPair } from \"../contracts/types\";\r\nimport { authService } from \"../services\";\r\nimport type { RefreshToken } from \"./refresh-token/refresh-token.model\";\r\n\r\nexport abstract class Auth<Schema extends ModelSchema = ModelSchema>\r\n extends Model<Schema>\r\n implements Authenticable\r\n{\r\n /**\r\n * Get user type\r\n */\r\n public abstract get userType(): string;\r\n\r\n /**\r\n * Get access token payload\r\n */\r\n public accessTokenPayload() {\r\n return authService.buildAccessTokenPayload(this);\r\n }\r\n\r\n /**\r\n * Create both access and refresh tokens\r\n */\r\n public async createTokenPair(deviceInfo?: DeviceInfo): Promise<TokenPair> {\r\n return authService.createTokenPair(this, deviceInfo);\r\n }\r\n\r\n /**\r\n * Generate access token\r\n */\r\n public async generateAccessToken(data?: any): Promise<AccessTokenOutput> {\r\n return authService.generateAccessToken(this, data);\r\n }\r\n\r\n /**\r\n * Generate refresh token\r\n */\r\n public async generateRefreshToken(deviceInfo?: DeviceInfo): Promise<RefreshToken | undefined> {\r\n return authService.createRefreshToken(this, deviceInfo);\r\n }\r\n\r\n /**\r\n * Remove current access token\r\n */\r\n public async removeAccessToken(token: string): Promise<void> {\r\n return authService.removeAccessToken(this, token);\r\n }\r\n\r\n /**\r\n * Remove refresh token\r\n */\r\n public async removeRefreshToken(token: string): Promise<void> {\r\n return authService.removeRefreshToken(this, token);\r\n }\r\n\r\n /**\r\n * Remove all access tokens\r\n */\r\n public async removeAllAccessTokens(): Promise<void> {\r\n return authService.removeAllAccessTokens(this);\r\n }\r\n\r\n /**\r\n * Revoke all tokens (logout from all devices)\r\n */\r\n public async revokeAllTokens(): Promise<void> {\r\n return authService.revokeAllTokens(this);\r\n }\r\n\r\n /**\r\n * Get active sessions\r\n */\r\n public async activeSessions(): Promise<RefreshToken[]> {\r\n return authService.getActiveSessions(this);\r\n }\r\n\r\n /**\r\n * Attempt to login the user\r\n */\r\n public static async attempt(this: ChildModel<Auth>, data: any): Promise<Auth | null> {\r\n return authService.attemptLogin(this, data);\r\n }\r\n\r\n /**\r\n * Confirm password\r\n */\r\n public async confirmPassword(password: string): Promise<boolean> {\r\n return authService.verifyPassword(password, this.string(\"password\")!);\r\n }\r\n}\r\n","import { AccessTokenMigration } from \"./access-token/migration\";\r\nimport { RefreshTokenMigration } from \"./refresh-token/migration\";\r\n\r\nexport * from \"./access-token\";\r\nexport * from \"./auth.model\";\r\nexport * from \"./refresh-token\";\r\n\r\nexport const authMigrations = [AccessTokenMigration, RefreshTokenMigration];\r\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ //#region ../../@warlock.js/auth/src/commands/auth-cleanup-command.d.ts
2
+ /**
3
+ * Register the auth:cleanup CLI command
4
+ *
5
+ * @example
6
+ * ```bash
7
+ * warlock auth:cleanup
8
+ * ```
9
+ */
10
+ declare function registerAuthCleanupCommand(): any;
11
+ //#endregion
12
+ export { registerAuthCleanupCommand };
13
+ //# sourceMappingURL=auth-cleanup-command.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-cleanup-command.d.mts","names":[],"sources":["../../../../../../@warlock.js/auth/src/commands/auth-cleanup-command.ts"],"mappings":";;AAYA;;;;AAA0C;;;iBAA1B,0BAAA,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { authService } from "../services/auth.service.mjs";
2
+ import { colors } from "@mongez/copper";
3
+ import { command } from "@warlock.js/core";
4
+
5
+ //#region ../../@warlock.js/auth/src/commands/auth-cleanup-command.ts
6
+ /**
7
+ * Register the auth:cleanup CLI command
8
+ *
9
+ * @example
10
+ * ```bash
11
+ * warlock auth:cleanup
12
+ * ```
13
+ */
14
+ function registerAuthCleanupCommand() {
15
+ return command({
16
+ name: "auth.cleanup",
17
+ description: "Remove expired refresh tokens from the database",
18
+ preload: {
19
+ env: true,
20
+ config: ["auth", "database"],
21
+ connectors: ["database"]
22
+ },
23
+ action: async () => {
24
+ console.log(colors.cyan("🧹 Cleaning up expired tokens..."));
25
+ const count = await authService.cleanupExpiredTokens();
26
+ if (count === 0) console.log(colors.green("✅ No expired tokens found."));
27
+ else console.log(colors.green(`✅ Removed ${count} expired token(s).`));
28
+ }
29
+ });
30
+ }
31
+
32
+ //#endregion
33
+ export { registerAuthCleanupCommand };
34
+ //# sourceMappingURL=auth-cleanup-command.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-cleanup-command.mjs","names":[],"sources":["../../../../../../@warlock.js/auth/src/commands/auth-cleanup-command.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { command } from \"@warlock.js/core\";\nimport { authService } from \"../services/auth.service\";\n\n/**\n * Register the auth:cleanup CLI command\n *\n * @example\n * ```bash\n * warlock auth:cleanup\n * ```\n */\nexport function registerAuthCleanupCommand() {\n return command({\n name: \"auth.cleanup\",\n description: \"Remove expired refresh tokens from the database\",\n preload: {\n env: true,\n config: [\"auth\", \"database\"],\n connectors: [\"database\"],\n },\n action: async () => {\n console.log(colors.cyan(\"🧹 Cleaning up expired tokens...\"));\n\n const count = await authService.cleanupExpiredTokens();\n\n if (count === 0) {\n console.log(colors.green(\"✅ No expired tokens found.\"));\n } else {\n console.log(colors.green(`✅ Removed ${count} expired token(s).`));\n }\n },\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,6BAA6B;CAC3C,OAAO,QAAQ;EACb,MAAM;EACN,aAAa;EACb,SAAS;GACP,KAAK;GACL,QAAQ,CAAC,QAAQ,UAAU;GAC3B,YAAY,CAAC,UAAU;EACzB;EACA,QAAQ,YAAY;GAClB,QAAQ,IAAI,OAAO,KAAK,kCAAkC,CAAC;GAE3D,MAAM,QAAQ,MAAM,YAAY,qBAAqB;GAErD,IAAI,UAAU,GACZ,QAAQ,IAAI,OAAO,MAAM,4BAA4B,CAAC;QAEtD,QAAQ,IAAI,OAAO,MAAM,aAAa,MAAM,mBAAmB,CAAC;EAEpE;CACF,CAAC;AACH"}
@@ -0,0 +1,5 @@
1
+ //#region ../../@warlock.js/auth/src/commands/jwt-secret-generator-command.d.ts
2
+ declare function registerJWTSecretGeneratorCommand(): any;
3
+ //#endregion
4
+ export { registerJWTSecretGeneratorCommand };
5
+ //# sourceMappingURL=jwt-secret-generator-command.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-secret-generator-command.d.mts","names":[],"sources":["../../../../../../@warlock.js/auth/src/commands/jwt-secret-generator-command.ts"],"mappings":";iBAGgB,iCAAA,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { generateJWTSecret } from "../services/generate-jwt-secret.mjs";
2
+ import { command } from "@warlock.js/core";
3
+
4
+ //#region ../../@warlock.js/auth/src/commands/jwt-secret-generator-command.ts
5
+ function registerJWTSecretGeneratorCommand() {
6
+ return command({
7
+ name: "jwt.generate",
8
+ description: "Generate JWT Secret key in .env file",
9
+ action: generateJWTSecret
10
+ });
11
+ }
12
+
13
+ //#endregion
14
+ export { registerJWTSecretGeneratorCommand };
15
+ //# sourceMappingURL=jwt-secret-generator-command.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-secret-generator-command.mjs","names":[],"sources":["../../../../../../@warlock.js/auth/src/commands/jwt-secret-generator-command.ts"],"sourcesContent":["import { command } from \"@warlock.js/core\";\r\nimport { generateJWTSecret } from \"../services/generate-jwt-secret\";\r\n\r\nexport function registerJWTSecretGeneratorCommand() {\r\n return command({\r\n name: \"jwt.generate\",\r\n description: \"Generate JWT Secret key in .env file\",\r\n action: generateJWTSecret,\r\n });\r\n}\r\n"],"mappings":";;;;AAGA,SAAgB,oCAAoC;CAClD,OAAO,QAAQ;EACb,MAAM;EACN,aAAa;EACb,QAAQ;CACV,CAAC;AACH"}
@@ -0,0 +1,40 @@
1
+ import { RefreshToken } from "../models/refresh-token/refresh-token.model.mjs";
2
+ import { AccessTokenOutput, DeviceInfo, TokenPair } from "./types.mjs";
3
+
4
+ //#region ../../@warlock.js/auth/src/contracts/auth-contract.d.ts
5
+ /**
6
+ * Surface every authenticable user model exposes once it extends the
7
+ * `Auth` base. The `Auth` class implements this contract; subclasses only
8
+ * need to provide the abstract `userType` getter.
9
+ *
10
+ * Kept in sync with `Auth` — if a method here drifts from the class, the
11
+ * `implements Authenticable` clause on `Auth` fails to compile.
12
+ */
13
+ interface Authenticable {
14
+ /**
15
+ * Discriminator identifying which user type this model represents.
16
+ * Drives token payloads and `authMiddleware` type checks.
17
+ */
18
+ get userType(): string;
19
+ /**
20
+ * Generate (and persist) an access token for this user.
21
+ * Pass a custom payload to override the default token claims.
22
+ */
23
+ generateAccessToken(payload?: Record<string, unknown>): Promise<AccessTokenOutput>;
24
+ /**
25
+ * Generate a refresh token for this user. Resolves to `undefined` when
26
+ * refresh tokens are disabled in config.
27
+ */
28
+ generateRefreshToken(deviceInfo?: DeviceInfo): Promise<RefreshToken | undefined>;
29
+ /**
30
+ * Issue both an access token and a refresh token in one call.
31
+ */
32
+ createTokenPair(deviceInfo?: DeviceInfo): Promise<TokenPair>;
33
+ /**
34
+ * Verify a plaintext password against this user's stored hash.
35
+ */
36
+ confirmPassword(password: string): Promise<boolean>;
37
+ }
38
+ //#endregion
39
+ export { Authenticable };
40
+ //# sourceMappingURL=auth-contract.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-contract.d.mts","names":[],"sources":["../../../../../../@warlock.js/auth/src/contracts/auth-contract.ts"],"mappings":";;;;;;AAWA;;;;;;UAAiB,aAAA;EAiBwC;;;;EAAA,IAZnD,QAAA;EAsB+B;;;;EAhBnC,mBAAA,CAAoB,OAAA,GAAU,MAAA,oBAA0B,OAAA,CAAQ,iBAAA;EAAlC;;;;EAM9B,oBAAA,CAAqB,UAAA,GAAa,UAAA,GAAa,OAAA,CAAQ,YAAA;EAArB;;;EAKlC,eAAA,CAAgB,UAAA,GAAa,UAAA,GAAa,OAAA,CAAQ,SAAA;EAAlD;;;EAKA,eAAA,CAAgB,QAAA,WAAmB,OAAA;AAAA"}
@@ -0,0 +1,2 @@
1
+ import { AccessTokenOutput, AuthConfigurations, DeviceInfo, LoginResult, LogoutWithoutTokenBehavior, NO_EXPIRATION, TokenPair } from "./types.mjs";
2
+ import { Authenticable } from "./auth-contract.mjs";
@@ -0,0 +1,170 @@
1
+ import { Auth } from "../models/auth.model.mjs";
2
+ import { ChildModel } from "@warlock.js/cascade";
3
+ import { Algorithm } from "fast-jwt";
4
+
5
+ //#region ../../@warlock.js/auth/src/contracts/types.d.ts
6
+ /**
7
+ * Symbol to indicate no expiration for tokens
8
+ * Use this when you explicitly want tokens to never expire
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // src/config/auth.ts
13
+ * import { NO_EXPIRATION, type AuthConfigurations } from "@warlock.js/auth";
14
+ *
15
+ * const authConfigurations: AuthConfigurations = {
16
+ * jwt: {
17
+ * secret: env("JWT_SECRET"),
18
+ * expiresIn: NO_EXPIRATION, // Token expires within 100 years
19
+ * },
20
+ * };
21
+ *
22
+ * export default authConfigurations;
23
+ * ```
24
+ */
25
+ declare const NO_EXPIRATION = "100y";
26
+ /**
27
+ * Behavior when logout is called without a refresh token
28
+ * - "revoke-all": Revoke all refresh tokens for the user (secure default)
29
+ * - "error": Return an error requiring the refresh token
30
+ */
31
+ type LogoutWithoutTokenBehavior = "revoke-all" | "error";
32
+ type AuthConfigurations = {
33
+ /**
34
+ * Define all user types
35
+ * This is important to differentiate between user types when validating and generating tokens
36
+ */
37
+ userType: {
38
+ [userType: string]: ChildModel<Auth>;
39
+ };
40
+ /**
41
+ * JWT configurations
42
+ */
43
+ jwt: {
44
+ /**
45
+ * JWT secret key for signing access tokens
46
+ */
47
+ secret: string;
48
+ /**
49
+ * JWT algorithm
50
+ * @default "HS256"
51
+ */
52
+ algorithm?: Algorithm;
53
+ /**
54
+ * Access token expiration time
55
+ * It accepts any value `ms` package accepts
56
+ * @example "1h" or NO_EXPIRATION
57
+ * @default "1h"
58
+ */
59
+ expiresIn?: string;
60
+ /**
61
+ * Refresh token configurations
62
+ */
63
+ refresh?: {
64
+ /**
65
+ * Separate secret for refresh tokens (recommended for security)
66
+ * If not provided, falls back to main JWT secret
67
+ */
68
+ secret?: string;
69
+ /**
70
+ * Enable refresh token
71
+ * @default true
72
+ */
73
+ enabled?: boolean;
74
+ /**
75
+ * Refresh token expiration time
76
+ * It accepts any value `ms` package accepts
77
+ * @example "7d" or "1w"
78
+ * @default "7d"
79
+ */
80
+ expiresIn?: string;
81
+ /**
82
+ * Enable token rotation (issue new refresh token on each use)
83
+ * Old refresh token is invalidated after use
84
+ * @default true
85
+ */
86
+ rotation?: boolean;
87
+ /**
88
+ * Maximum number of active refresh tokens per user
89
+ * When exceeded, oldest tokens are revoked
90
+ * @default 5
91
+ */
92
+ maxPerUser?: number;
93
+ /**
94
+ * Behavior when logout is called without a refresh token
95
+ * - "revoke-all": Revoke all tokens for security (default)
96
+ * - "error": Require refresh token, return error if missing
97
+ * @default "revoke-all"
98
+ */
99
+ logoutWithoutToken?: LogoutWithoutTokenBehavior;
100
+ };
101
+ };
102
+ /**
103
+ * Password configurations
104
+ */
105
+ password?: {
106
+ /**
107
+ * Password salt
108
+ * The higher the salt, the more secure the password is
109
+ * But, it will take more time to generate the password
110
+ * @default 12
111
+ */
112
+ salt?: number;
113
+ };
114
+ };
115
+ type AccessTokenOutput = {
116
+ /**
117
+ * JWT Token
118
+ */
119
+ token: string;
120
+ /**
121
+ * Exprie time in ISO format UTC time
122
+ */
123
+ expiresAt: string;
124
+ };
125
+ /**
126
+ * Token pair returned after login or token refresh
127
+ */
128
+ type TokenPair = {
129
+ /**
130
+ * JWT access token (short-lived)
131
+ */
132
+ accessToken: AccessTokenOutput;
133
+ /**
134
+ * JWT refresh token (long-lived)
135
+ */
136
+ refreshToken?: AccessTokenOutput;
137
+ };
138
+ /**
139
+ * Device information for session tracking
140
+ */
141
+ type DeviceInfo = {
142
+ /**
143
+ * User agent string from request
144
+ */
145
+ userAgent?: string;
146
+ /**
147
+ * Client IP address
148
+ */
149
+ ip?: string;
150
+ /**
151
+ * Optional device identifier
152
+ */
153
+ deviceId?: string;
154
+ /**
155
+ * Token family ID (for rotation tracking)
156
+ * @internal
157
+ */
158
+ familyId?: string;
159
+ /**
160
+ * Access token payload
161
+ */
162
+ payload?: Record<string, any>;
163
+ };
164
+ type LoginResult<UserType extends Auth> = {
165
+ user: UserType;
166
+ tokens: TokenPair;
167
+ };
168
+ //#endregion
169
+ export { AccessTokenOutput, AuthConfigurations, DeviceInfo, LoginResult, LogoutWithoutTokenBehavior, NO_EXPIRATION, TokenPair };
170
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../../../../../../@warlock.js/auth/src/contracts/types.ts"],"mappings":";;;;;;;AAuBA;;;;AAA0B;AAO1B;;;;AAAsC;AAEtC;;;;;;;cATa,aAAA;;;;;;KAOD,0BAAA;AAAA,KAEA,kBAAA;EAoBR;;;;EAfF,QAAA;IAAA,CACG,QAAA,WAAmB,UAAA,CAAW,IAAA;EAAA;EAgD7B;;;EA3CJ,GAAA;IA8DA;;;IA1DE,MAAA;IAqEQ;;;;IAhER,SAAA,GAAY,SAAA;IA8EJ;;;;;;IAvER,SAAA;IA+Ea;;AAAiB;IA3E9B,OAAA;MAiFkB;;;;MA5EhB,MAAA;MAwFJ;;;;MAnFI,OAAA;MA4FY;AAGlB;;;;;MAxFM,SAAA;MA0Fa;;;;;MApFb,QAAA;MAoFJ;;;AAAiB;;MA9Eb,UAAA;;;;;;;MAOA,kBAAA,GAAqB,0BAAA;IAAA;EAAA;;;;EAMzB,QAAA;;;;;;;IAOE,IAAA;EAAA;AAAA;AAAA,KAIQ,iBAAA;;;;EAIV,KAAA;;;;EAIA,SAAS;AAAA;;;;KAMC,SAAA;;;;EAIV,WAAA,EAAa,iBAAA;;;;EAIb,YAAA,GAAe,iBAAiB;AAAA;;;;KAMtB,UAAA;;;;EAIV,SAAA;;;;EAIA,EAAA;;;;EAIA,QAAA;;;;;EAKA,QAAA;;;;EAIA,OAAA,GAAU,MAAM;AAAA;AAAA,KAGN,WAAA,kBAA6B,IAAA;EACvC,IAAA,EAAM,QAAA;EACN,MAAA,EAAQ,SAAA;AAAA"}
@@ -0,0 +1,25 @@
1
+ //#region ../../@warlock.js/auth/src/contracts/types.ts
2
+ /**
3
+ * Symbol to indicate no expiration for tokens
4
+ * Use this when you explicitly want tokens to never expire
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // src/config/auth.ts
9
+ * import { NO_EXPIRATION, type AuthConfigurations } from "@warlock.js/auth";
10
+ *
11
+ * const authConfigurations: AuthConfigurations = {
12
+ * jwt: {
13
+ * secret: env("JWT_SECRET"),
14
+ * expiresIn: NO_EXPIRATION, // Token expires within 100 years
15
+ * },
16
+ * };
17
+ *
18
+ * export default authConfigurations;
19
+ * ```
20
+ */
21
+ const NO_EXPIRATION = "100y";
22
+
23
+ //#endregion
24
+ export { NO_EXPIRATION };
25
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.mjs","names":[],"sources":["../../../../../../@warlock.js/auth/src/contracts/types.ts"],"sourcesContent":["import { ChildModel } from \"@warlock.js/cascade\";\r\nimport { type Algorithm } from \"fast-jwt\";\r\nimport type { Auth } from \"../models/auth.model\";\r\n\r\n/**\r\n * Symbol to indicate no expiration for tokens\r\n * Use this when you explicitly want tokens to never expire\r\n *\r\n * @example\r\n * ```typescript\r\n * // src/config/auth.ts\r\n * import { NO_EXPIRATION, type AuthConfigurations } from \"@warlock.js/auth\";\r\n *\r\n * const authConfigurations: AuthConfigurations = {\r\n * jwt: {\r\n * secret: env(\"JWT_SECRET\"),\r\n * expiresIn: NO_EXPIRATION, // Token expires within 100 years\r\n * },\r\n * };\r\n *\r\n * export default authConfigurations;\r\n * ```\r\n */\r\nexport const NO_EXPIRATION = \"100y\";\r\n\r\n/**\r\n * Behavior when logout is called without a refresh token\r\n * - \"revoke-all\": Revoke all refresh tokens for the user (secure default)\r\n * - \"error\": Return an error requiring the refresh token\r\n */\r\nexport type LogoutWithoutTokenBehavior = \"revoke-all\" | \"error\";\r\n\r\nexport type AuthConfigurations = {\r\n /**\r\n * Define all user types\r\n * This is important to differentiate between user types when validating and generating tokens\r\n */\r\n userType: {\r\n [userType: string]: ChildModel<Auth>;\r\n };\r\n /**\r\n * JWT configurations\r\n */\r\n jwt: {\r\n /**\r\n * JWT secret key for signing access tokens\r\n */\r\n secret: string;\r\n /**\r\n * JWT algorithm\r\n * @default \"HS256\"\r\n */\r\n algorithm?: Algorithm;\r\n /**\r\n * Access token expiration time\r\n * It accepts any value `ms` package accepts\r\n * @example \"1h\" or NO_EXPIRATION\r\n * @default \"1h\"\r\n */\r\n expiresIn?: string;\r\n /**\r\n * Refresh token configurations\r\n */\r\n refresh?: {\r\n /**\r\n * Separate secret for refresh tokens (recommended for security)\r\n * If not provided, falls back to main JWT secret\r\n */\r\n secret?: string;\r\n /**\r\n * Enable refresh token\r\n * @default true\r\n */\r\n enabled?: boolean;\r\n /**\r\n * Refresh token expiration time\r\n * It accepts any value `ms` package accepts\r\n * @example \"7d\" or \"1w\"\r\n * @default \"7d\"\r\n */\r\n expiresIn?: string;\r\n /**\r\n * Enable token rotation (issue new refresh token on each use)\r\n * Old refresh token is invalidated after use\r\n * @default true\r\n */\r\n rotation?: boolean;\r\n /**\r\n * Maximum number of active refresh tokens per user\r\n * When exceeded, oldest tokens are revoked\r\n * @default 5\r\n */\r\n maxPerUser?: number;\r\n /**\r\n * Behavior when logout is called without a refresh token\r\n * - \"revoke-all\": Revoke all tokens for security (default)\r\n * - \"error\": Require refresh token, return error if missing\r\n * @default \"revoke-all\"\r\n */\r\n logoutWithoutToken?: LogoutWithoutTokenBehavior;\r\n };\r\n };\r\n /**\r\n * Password configurations\r\n */\r\n password?: {\r\n /**\r\n * Password salt\r\n * The higher the salt, the more secure the password is\r\n * But, it will take more time to generate the password\r\n * @default 12\r\n */\r\n salt?: number;\r\n };\r\n};\r\n\r\nexport type AccessTokenOutput = {\r\n /**\r\n * JWT Token\r\n */\r\n token: string;\r\n /**\r\n * Exprie time in ISO format UTC time\r\n */\r\n expiresAt: string;\r\n};\r\n\r\n/**\r\n * Token pair returned after login or token refresh\r\n */\r\nexport type TokenPair = {\r\n /**\r\n * JWT access token (short-lived)\r\n */\r\n accessToken: AccessTokenOutput;\r\n /**\r\n * JWT refresh token (long-lived)\r\n */\r\n refreshToken?: AccessTokenOutput;\r\n};\r\n\r\n/**\r\n * Device information for session tracking\r\n */\r\nexport type DeviceInfo = {\r\n /**\r\n * User agent string from request\r\n */\r\n userAgent?: string;\r\n /**\r\n * Client IP address\r\n */\r\n ip?: string;\r\n /**\r\n * Optional device identifier\r\n */\r\n deviceId?: string;\r\n /**\r\n * Token family ID (for rotation tracking)\r\n * @internal\r\n */\r\n familyId?: string;\r\n /**\r\n * Access token payload\r\n */\r\n payload?: Record<string, any>;\r\n};\r\n\r\nexport type LoginResult<UserType extends Auth> = {\r\n user: UserType;\r\n tokens: TokenPair;\r\n};\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,gBAAgB"}
@@ -0,0 +1,15 @@
1
+ import { registerAuthCleanupCommand } from "./commands/auth-cleanup-command.mjs";
2
+ import { registerJWTSecretGeneratorCommand } from "./commands/jwt-secret-generator-command.mjs";
3
+ import { RefreshToken } from "./models/refresh-token/refresh-token.model.mjs";
4
+ import { Auth } from "./models/auth.model.mjs";
5
+ import { AccessTokenOutput, AuthConfigurations, DeviceInfo, LoginResult, LogoutWithoutTokenBehavior, NO_EXPIRATION, TokenPair } from "./contracts/types.mjs";
6
+ import { Authenticable } from "./contracts/auth-contract.mjs";
7
+ import { authMiddleware } from "./middleware/auth.middleware.mjs";
8
+ import { AccessToken } from "./models/access-token/access-token.model.mjs";
9
+ import { authMigrations } from "./models/index.mjs";
10
+ import { AuthEventCallback, AuthEventName, AuthEventPayloads, authEvents } from "./services/auth-events.mjs";
11
+ import { authService } from "./services/auth.service.mjs";
12
+ import { generateJWTSecret } from "./services/generate-jwt-secret.mjs";
13
+ import { jwt } from "./services/jwt.mjs";
14
+ import { AuthErrorCodes } from "./utils/auth-error-codes.mjs";
15
+ export { AccessToken, AccessTokenOutput, Auth, AuthConfigurations, AuthErrorCodes, AuthEventCallback, AuthEventName, AuthEventPayloads, Authenticable, DeviceInfo, LoginResult, LogoutWithoutTokenBehavior, NO_EXPIRATION, RefreshToken, TokenPair, authEvents, authMiddleware, authMigrations, authService, generateJWTSecret, jwt, registerAuthCleanupCommand, registerJWTSecretGeneratorCommand };
package/esm/index.mjs ADDED
@@ -0,0 +1,17 @@
1
+ import { AccessToken } from "./models/access-token/access-token.model.mjs";
2
+ import { RefreshToken } from "./models/refresh-token/refresh-token.model.mjs";
3
+ import { authEvents } from "./services/auth-events.mjs";
4
+ import { jwt } from "./services/jwt.mjs";
5
+ import { authService } from "./services/auth.service.mjs";
6
+ import { registerAuthCleanupCommand } from "./commands/auth-cleanup-command.mjs";
7
+ import { generateJWTSecret } from "./services/generate-jwt-secret.mjs";
8
+ import { registerJWTSecretGeneratorCommand } from "./commands/jwt-secret-generator-command.mjs";
9
+ import { NO_EXPIRATION } from "./contracts/types.mjs";
10
+ import { AuthErrorCodes } from "./utils/auth-error-codes.mjs";
11
+ import { authMiddleware } from "./middleware/auth.middleware.mjs";
12
+ import "./middleware/index.mjs";
13
+ import "./services/index.mjs";
14
+ import { Auth } from "./models/auth.model.mjs";
15
+ import { authMigrations } from "./models/index.mjs";
16
+
17
+ export { AccessToken, Auth, AuthErrorCodes, NO_EXPIRATION, RefreshToken, authEvents, authMiddleware, authMigrations, authService, generateJWTSecret, jwt, registerAuthCleanupCommand, registerJWTSecretGeneratorCommand };
@@ -0,0 +1,22 @@
1
+ //#region ../../@warlock.js/auth/src/middleware/auth.middleware.d.ts
2
+ /**
3
+ * Build a route gate that always requires an authenticated request.
4
+ *
5
+ * The argument is mandatory and selects which user types may pass:
6
+ * - `[]` — any authenticated user (token required, type not checked).
7
+ * - `"admin"` / `["admin", "staff"]` — token required AND the user's
8
+ * `userType` must be one of the listed types.
9
+ *
10
+ * There is no anonymous/optional mode: a request without a valid access
11
+ * token is always rejected with `401`. Routes that should be public
12
+ * simply omit the middleware.
13
+ *
14
+ * @example
15
+ * router.get("/account", authMiddleware([]), accountController);
16
+ * router.get("/admin", authMiddleware("admin"), adminController);
17
+ * router.get("/back-office", authMiddleware(["admin", "staff"]), backOfficeController);
18
+ */
19
+ declare function authMiddleware(allowedUserType: string | string[]): Middleware;
20
+ //#endregion
21
+ export { authMiddleware };
22
+ //# sourceMappingURL=auth.middleware.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.middleware.d.mts","names":[],"sources":["../../../../../../@warlock.js/auth/src/middleware/auth.middleware.ts"],"mappings":";;AAuBA;;;;AAAiE;;;;;;;;;;;;iBAAjD,cAAA,CAAe,eAAA,sBAAkC,UAAA"}
@@ -0,0 +1,72 @@
1
+ import { AccessToken } from "../models/access-token/access-token.model.mjs";
2
+ import "../models/access-token/index.mjs";
3
+ import { jwt } from "../services/jwt.mjs";
4
+ import { AuthErrorCodes } from "../utils/auth-error-codes.mjs";
5
+ import { config, t } from "@warlock.js/core";
6
+ import { log } from "@warlock.js/logger";
7
+
8
+ //#region ../../@warlock.js/auth/src/middleware/auth.middleware.ts
9
+ /**
10
+ * Build a route gate that always requires an authenticated request.
11
+ *
12
+ * The argument is mandatory and selects which user types may pass:
13
+ * - `[]` — any authenticated user (token required, type not checked).
14
+ * - `"admin"` / `["admin", "staff"]` — token required AND the user's
15
+ * `userType` must be one of the listed types.
16
+ *
17
+ * There is no anonymous/optional mode: a request without a valid access
18
+ * token is always rejected with `401`. Routes that should be public
19
+ * simply omit the middleware.
20
+ *
21
+ * @example
22
+ * router.get("/account", authMiddleware([]), accountController);
23
+ * router.get("/admin", authMiddleware("admin"), adminController);
24
+ * router.get("/back-office", authMiddleware(["admin", "staff"]), backOfficeController);
25
+ */
26
+ function authMiddleware(allowedUserType) {
27
+ const allowedTypes = Array.isArray(allowedUserType) ? allowedUserType : [allowedUserType];
28
+ const auth = async (request, response) => {
29
+ try {
30
+ const authorizationValue = request.authorizationValue;
31
+ if (!authorizationValue) return response.unauthorized({
32
+ error: t("auth.errors.missingAccessToken"),
33
+ errorCode: "EC001"
34
+ });
35
+ const user = await jwt.verify(authorizationValue);
36
+ request.decodedAccessToken = user;
37
+ const accessToken = await AccessToken.first({ token: authorizationValue });
38
+ if (!accessToken) return response.unauthorized({
39
+ error: t("auth.errors.invalidAccessToken"),
40
+ errorCode: "EC002"
41
+ });
42
+ const userType = user.userType || accessToken.get("userType");
43
+ if (allowedTypes.length && !allowedTypes.includes(userType)) return response.unauthorized({
44
+ error: t("auth.errors.unauthorized"),
45
+ errorCode: "EC003"
46
+ });
47
+ const UserModel = config.key(`auth.userType.${userType}`);
48
+ if (!UserModel) throw new Error(`User type ${userType} is unknown type.`);
49
+ const currentUser = await UserModel.find(user.id);
50
+ if (!currentUser) {
51
+ accessToken.destroy();
52
+ return response.unauthorized({
53
+ error: t("auth.errors.invalidAccessToken"),
54
+ errorCode: "EC002"
55
+ });
56
+ }
57
+ request.user = currentUser;
58
+ } catch (err) {
59
+ log.error("http", "auth", err);
60
+ request.clearCurrentUser();
61
+ return response.unauthorized({
62
+ error: t("auth.errors.invalidAccessToken"),
63
+ errorCode: "EC002"
64
+ });
65
+ }
66
+ };
67
+ return auth;
68
+ }
69
+
70
+ //#endregion
71
+ export { authMiddleware };
72
+ //# sourceMappingURL=auth.middleware.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.middleware.mjs","names":[],"sources":["../../../../../../@warlock.js/auth/src/middleware/auth.middleware.ts"],"sourcesContent":["import { config, t, type Middleware, type Request, type Response } from \"@warlock.js/core\";\r\nimport { log } from \"@warlock.js/logger\";\r\nimport { AccessToken } from \"../models/access-token\";\r\nimport { jwt } from \"../services/jwt\";\r\nimport { AuthErrorCodes } from \"../utils/auth-error-codes\";\r\n\r\n/**\r\n * Build a route gate that always requires an authenticated request.\r\n *\r\n * The argument is mandatory and selects which user types may pass:\r\n * - `[]` — any authenticated user (token required, type not checked).\r\n * - `\"admin\"` / `[\"admin\", \"staff\"]` — token required AND the user's\r\n * `userType` must be one of the listed types.\r\n *\r\n * There is no anonymous/optional mode: a request without a valid access\r\n * token is always rejected with `401`. Routes that should be public\r\n * simply omit the middleware.\r\n *\r\n * @example\r\n * router.get(\"/account\", authMiddleware([]), accountController);\r\n * router.get(\"/admin\", authMiddleware(\"admin\"), adminController);\r\n * router.get(\"/back-office\", authMiddleware([\"admin\", \"staff\"]), backOfficeController);\r\n */\r\nexport function authMiddleware(allowedUserType: string | string[]) {\r\n const allowedTypes = Array.isArray(allowedUserType) ? allowedUserType : [allowedUserType];\r\n\r\n const auth: Middleware = async (request: Request, response: Response) => {\r\n try {\r\n const authorizationValue = request.authorizationValue;\r\n\r\n if (!authorizationValue) {\r\n return response.unauthorized({\r\n error: t(\"auth.errors.missingAccessToken\"),\r\n errorCode: AuthErrorCodes.MissingAccessToken,\r\n });\r\n }\r\n\r\n // get current user jwt\r\n const user = await jwt.verify(authorizationValue);\r\n\r\n // store decoded access token object in request object\r\n request.decodedAccessToken = user;\r\n // use our own jwt verify to verify the token\r\n const accessToken = await AccessToken.first({\r\n token: authorizationValue,\r\n });\r\n\r\n if (!accessToken) {\r\n return response.unauthorized({\r\n error: t(\"auth.errors.invalidAccessToken\"),\r\n errorCode: AuthErrorCodes.InvalidAccessToken,\r\n });\r\n }\r\n\r\n // now, we need to get an instance of user using its corresponding model\r\n const userType = user.userType || accessToken.get(\"userType\");\r\n\r\n // check if the user type is allowed\r\n if (allowedTypes.length && !allowedTypes.includes(userType)) {\r\n return response.unauthorized({\r\n error: t(\"auth.errors.unauthorized\"),\r\n errorCode: AuthErrorCodes.Unauthorized,\r\n });\r\n }\r\n\r\n // get user model class\r\n const UserModel = config.key(`auth.userType.${userType}`);\r\n\r\n if (!UserModel) {\r\n throw new Error(`User type ${userType} is unknown type.`);\r\n }\r\n\r\n // get user model instance\r\n const currentUser = await UserModel.find(user.id);\r\n\r\n if (!currentUser) {\r\n accessToken.destroy();\r\n return response.unauthorized({\r\n error: t(\"auth.errors.invalidAccessToken\"),\r\n errorCode: AuthErrorCodes.InvalidAccessToken,\r\n });\r\n }\r\n\r\n // update last access\r\n // accessToken.set(\"lastAccess\", new Date());\r\n // await accessToken.save({ skipEvents: true });\r\n\r\n // set current user\r\n request.user = currentUser;\r\n } catch (err: any) {\r\n log.error(\"http\", \"auth\", err);\r\n\r\n request.clearCurrentUser();\r\n\r\n return response.unauthorized({\r\n error: t(\"auth.errors.invalidAccessToken\"),\r\n errorCode: AuthErrorCodes.InvalidAccessToken,\r\n });\r\n }\r\n };\r\n\r\n return auth;\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,eAAe,iBAAoC;CACjE,MAAM,eAAe,MAAM,QAAQ,eAAe,IAAI,kBAAkB,CAAC,eAAe;CAExF,MAAM,OAAmB,OAAO,SAAkB,aAAuB;EACvE,IAAI;GACF,MAAM,qBAAqB,QAAQ;GAEnC,IAAI,CAAC,oBACH,OAAO,SAAS,aAAa;IAC3B,OAAO,EAAE,gCAAgC;IACzC;GACF,CAAC;GAIH,MAAM,OAAO,MAAM,IAAI,OAAO,kBAAkB;GAGhD,QAAQ,qBAAqB;GAE7B,MAAM,cAAc,MAAM,YAAY,MAAM,EAC1C,OAAO,mBACT,CAAC;GAED,IAAI,CAAC,aACH,OAAO,SAAS,aAAa;IAC3B,OAAO,EAAE,gCAAgC;IACzC;GACF,CAAC;GAIH,MAAM,WAAW,KAAK,YAAY,YAAY,IAAI,UAAU;GAG5D,IAAI,aAAa,UAAU,CAAC,aAAa,SAAS,QAAQ,GACxD,OAAO,SAAS,aAAa;IAC3B,OAAO,EAAE,0BAA0B;IACnC;GACF,CAAC;GAIH,MAAM,YAAY,OAAO,IAAI,iBAAiB,UAAU;GAExD,IAAI,CAAC,WACH,MAAM,IAAI,MAAM,aAAa,SAAS,kBAAkB;GAI1D,MAAM,cAAc,MAAM,UAAU,KAAK,KAAK,EAAE;GAEhD,IAAI,CAAC,aAAa;IAChB,YAAY,QAAQ;IACpB,OAAO,SAAS,aAAa;KAC3B,OAAO,EAAE,gCAAgC;KACzC;IACF,CAAC;GACH;GAOA,QAAQ,OAAO;EACjB,SAAS,KAAU;GACjB,IAAI,MAAM,QAAQ,QAAQ,GAAG;GAE7B,QAAQ,iBAAiB;GAEzB,OAAO,SAAS,aAAa;IAC3B,OAAO,EAAE,gCAAgC;IACzC;GACF,CAAC;EACH;CACF;CAEA,OAAO;AACT"}
@@ -0,0 +1,3 @@
1
+ import { authMiddleware } from "./auth.middleware.mjs";
2
+
3
+ export { };