couchloop-eq-mcp 1.0.3 → 1.0.5

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 (285) hide show
  1. package/README.md +24 -11
  2. package/dist/clients/shrinkChatClient.js +1 -1
  3. package/dist/clients/shrinkChatClient.js.map +1 -1
  4. package/dist/developer/analyzers/bloat-detector.d.ts +89 -0
  5. package/dist/developer/analyzers/bloat-detector.d.ts.map +1 -0
  6. package/dist/developer/analyzers/bloat-detector.js +483 -0
  7. package/dist/developer/analyzers/bloat-detector.js.map +1 -0
  8. package/dist/developer/backup/auto-backup.d.ts +96 -0
  9. package/dist/developer/backup/auto-backup.d.ts.map +1 -0
  10. package/dist/developer/backup/auto-backup.js +346 -0
  11. package/dist/developer/backup/auto-backup.js.map +1 -0
  12. package/dist/developer/blockers/package-blocker.d.ts +33 -0
  13. package/dist/developer/blockers/package-blocker.d.ts.map +1 -0
  14. package/dist/developer/blockers/package-blocker.js +224 -0
  15. package/dist/developer/blockers/package-blocker.js.map +1 -0
  16. package/dist/developer/evaluators/ai-error-preventer.d.ts +54 -0
  17. package/dist/developer/evaluators/ai-error-preventer.d.ts.map +1 -0
  18. package/dist/developer/evaluators/ai-error-preventer.js +270 -0
  19. package/dist/developer/evaluators/ai-error-preventer.js.map +1 -0
  20. package/dist/developer/evaluators/build-context-detector.d.ts +44 -0
  21. package/dist/developer/evaluators/build-context-detector.d.ts.map +1 -0
  22. package/dist/developer/evaluators/build-context-detector.js +258 -0
  23. package/dist/developer/evaluators/build-context-detector.js.map +1 -0
  24. package/dist/developer/evaluators/package-evaluator.d.ts +37 -0
  25. package/dist/developer/evaluators/package-evaluator.d.ts.map +1 -0
  26. package/dist/developer/evaluators/package-evaluator.js +278 -0
  27. package/dist/developer/evaluators/package-evaluator.js.map +1 -0
  28. package/dist/developer/guards/file-guardian.d.ts +79 -0
  29. package/dist/developer/guards/file-guardian.d.ts.map +1 -0
  30. package/dist/developer/guards/file-guardian.js +309 -0
  31. package/dist/developer/guards/file-guardian.js.map +1 -0
  32. package/dist/developer/managers/context-manager.d.ts +61 -0
  33. package/dist/developer/managers/context-manager.d.ts.map +1 -0
  34. package/dist/developer/managers/context-manager.js +302 -0
  35. package/dist/developer/managers/context-manager.js.map +1 -0
  36. package/dist/developer/metrics/complexity-calculator.d.ts +52 -0
  37. package/dist/developer/metrics/complexity-calculator.d.ts.map +1 -0
  38. package/dist/developer/metrics/complexity-calculator.js +259 -0
  39. package/dist/developer/metrics/complexity-calculator.js.map +1 -0
  40. package/dist/developer/reports/review-summary.d.ts +49 -0
  41. package/dist/developer/reports/review-summary.d.ts.map +1 -0
  42. package/dist/developer/reports/review-summary.js +249 -0
  43. package/dist/developer/reports/review-summary.js.map +1 -0
  44. package/dist/developer/scanners/review-assistant.d.ts +41 -0
  45. package/dist/developer/scanners/review-assistant.d.ts.map +1 -0
  46. package/dist/developer/scanners/review-assistant.js +374 -0
  47. package/dist/developer/scanners/review-assistant.js.map +1 -0
  48. package/dist/developer/scanners/secret-scanner.d.ts +66 -0
  49. package/dist/developer/scanners/secret-scanner.d.ts.map +1 -0
  50. package/dist/developer/scanners/secret-scanner.js +287 -0
  51. package/dist/developer/scanners/secret-scanner.js.map +1 -0
  52. package/dist/developer/scanners/sql-injection-detector.d.ts +54 -0
  53. package/dist/developer/scanners/sql-injection-detector.d.ts.map +1 -0
  54. package/dist/developer/scanners/sql-injection-detector.js +174 -0
  55. package/dist/developer/scanners/sql-injection-detector.js.map +1 -0
  56. package/dist/developer/scanners/xss-detector.d.ts +60 -0
  57. package/dist/developer/scanners/xss-detector.d.ts.map +1 -0
  58. package/dist/developer/scanners/xss-detector.js +229 -0
  59. package/dist/developer/scanners/xss-detector.js.map +1 -0
  60. package/dist/developer/types/ai-errors.d.ts +34 -0
  61. package/dist/developer/types/ai-errors.d.ts.map +1 -0
  62. package/dist/developer/types/ai-errors.js +271 -0
  63. package/dist/developer/types/ai-errors.js.map +1 -0
  64. package/dist/developer/types/package.d.ts +32 -0
  65. package/dist/developer/types/package.d.ts.map +1 -0
  66. package/dist/developer/types/package.js +5 -0
  67. package/dist/developer/types/package.js.map +1 -0
  68. package/dist/developer/updaters/dependency-updater.d.ts +102 -0
  69. package/dist/developer/updaters/dependency-updater.d.ts.map +1 -0
  70. package/dist/developer/updaters/dependency-updater.js +472 -0
  71. package/dist/developer/updaters/dependency-updater.js.map +1 -0
  72. package/dist/developer/validators/cargo.d.ts +14 -0
  73. package/dist/developer/validators/cargo.d.ts.map +1 -0
  74. package/dist/developer/validators/cargo.js +132 -0
  75. package/dist/developer/validators/cargo.js.map +1 -0
  76. package/dist/developer/validators/gem.d.ts +14 -0
  77. package/dist/developer/validators/gem.d.ts.map +1 -0
  78. package/dist/developer/validators/gem.js +85 -0
  79. package/dist/developer/validators/gem.js.map +1 -0
  80. package/dist/developer/validators/go.d.ts +14 -0
  81. package/dist/developer/validators/go.d.ts.map +1 -0
  82. package/dist/developer/validators/go.js +138 -0
  83. package/dist/developer/validators/go.js.map +1 -0
  84. package/dist/developer/validators/maven.d.ts +14 -0
  85. package/dist/developer/validators/maven.d.ts.map +1 -0
  86. package/dist/developer/validators/maven.js +99 -0
  87. package/dist/developer/validators/maven.js.map +1 -0
  88. package/dist/developer/validators/npm.d.ts +14 -0
  89. package/dist/developer/validators/npm.d.ts.map +1 -0
  90. package/dist/developer/validators/npm.js +96 -0
  91. package/dist/developer/validators/npm.js.map +1 -0
  92. package/dist/developer/validators/nuget.d.ts +15 -0
  93. package/dist/developer/validators/nuget.d.ts.map +1 -0
  94. package/dist/developer/validators/nuget.js +107 -0
  95. package/dist/developer/validators/nuget.js.map +1 -0
  96. package/dist/developer/validators/pypi.d.ts +14 -0
  97. package/dist/developer/validators/pypi.d.ts.map +1 -0
  98. package/dist/developer/validators/pypi.js +118 -0
  99. package/dist/developer/validators/pypi.js.map +1 -0
  100. package/dist/developer/validators/registry-manager.d.ts +37 -0
  101. package/dist/developer/validators/registry-manager.d.ts.map +1 -0
  102. package/dist/developer/validators/registry-manager.js +89 -0
  103. package/dist/developer/validators/registry-manager.js.map +1 -0
  104. package/dist/developer/validators/version-checker.d.ts +145 -0
  105. package/dist/developer/validators/version-checker.d.ts.map +1 -0
  106. package/dist/developer/validators/version-checker.js +529 -0
  107. package/dist/developer/validators/version-checker.js.map +1 -0
  108. package/dist/server/index.js.map +1 -1
  109. package/dist/server/middleware/auth.d.ts +7 -9
  110. package/dist/server/middleware/auth.d.ts.map +1 -1
  111. package/dist/server/middleware/auth.js.map +1 -1
  112. package/dist/tools/check-versions.d.ts +100 -0
  113. package/dist/tools/check-versions.d.ts.map +1 -0
  114. package/dist/tools/check-versions.js +328 -0
  115. package/dist/tools/check-versions.js.map +1 -0
  116. package/dist/tools/detect-code-smell.d.ts +9 -0
  117. package/dist/tools/detect-code-smell.d.ts.map +1 -0
  118. package/dist/tools/detect-code-smell.js +231 -0
  119. package/dist/tools/detect-code-smell.js.map +1 -0
  120. package/dist/tools/index.d.ts +471 -0
  121. package/dist/tools/index.d.ts.map +1 -1
  122. package/dist/tools/index.js +178 -0
  123. package/dist/tools/index.js.map +1 -1
  124. package/dist/tools/journey.js +1 -1
  125. package/dist/tools/journey.js.map +1 -1
  126. package/dist/tools/pre-review-code.d.ts +71 -0
  127. package/dist/tools/pre-review-code.d.ts.map +1 -0
  128. package/dist/tools/pre-review-code.js +159 -0
  129. package/dist/tools/pre-review-code.js.map +1 -0
  130. package/dist/tools/preserve-context.d.ts +27 -0
  131. package/dist/tools/preserve-context.d.ts.map +1 -0
  132. package/dist/tools/preserve-context.js +98 -0
  133. package/dist/tools/preserve-context.js.map +1 -0
  134. package/dist/tools/protect-files.d.ts +224 -0
  135. package/dist/tools/protect-files.d.ts.map +1 -0
  136. package/dist/tools/protect-files.js +286 -0
  137. package/dist/tools/protect-files.js.map +1 -0
  138. package/dist/tools/scan-security.d.ts +38 -0
  139. package/dist/tools/scan-security.d.ts.map +1 -0
  140. package/dist/tools/scan-security.js +237 -0
  141. package/dist/tools/scan-security.js.map +1 -0
  142. package/dist/tools/validate_packages.d.ts +8 -0
  143. package/dist/tools/validate_packages.d.ts.map +1 -0
  144. package/dist/tools/validate_packages.js +159 -0
  145. package/dist/tools/validate_packages.js.map +1 -0
  146. package/dist/types/auth.d.ts +18 -18
  147. package/dist/types/auth.d.ts.map +1 -1
  148. package/dist/types/auth.js +91 -36
  149. package/dist/types/auth.js.map +1 -1
  150. package/dist/types/context.d.ts +46 -0
  151. package/dist/types/context.d.ts.map +1 -0
  152. package/dist/types/context.js +17 -0
  153. package/dist/types/context.js.map +1 -0
  154. package/dist/types/file-protection.d.ts +50 -0
  155. package/dist/types/file-protection.d.ts.map +1 -0
  156. package/dist/types/file-protection.js +9 -0
  157. package/dist/types/file-protection.js.map +1 -0
  158. package/dist/utils/errorHandler.d.ts.map +1 -1
  159. package/dist/utils/errorHandler.js +2 -1
  160. package/dist/utils/errorHandler.js.map +1 -1
  161. package/package.json +23 -2
  162. package/dist/db/migrate.d.ts +0 -4
  163. package/dist/db/migrate.d.ts.map +0 -1
  164. package/dist/db/migrate.js +0 -34
  165. package/dist/db/migrate.js.map +0 -1
  166. package/dist/db/migrations/schema.d.ts +0 -1074
  167. package/dist/db/migrations/schema.d.ts.map +0 -1
  168. package/dist/db/migrations/schema.js +0 -160
  169. package/dist/db/migrations/schema.js.map +0 -1
  170. package/dist/db/schema.d.ts +0 -1576
  171. package/dist/db/schema.d.ts.map +0 -1
  172. package/dist/db/schema.js +0 -204
  173. package/dist/db/schema.js.map +0 -1
  174. package/dist/db/seed.d.ts +0 -4
  175. package/dist/db/seed.d.ts.map +0 -1
  176. package/dist/db/seed.js +0 -57
  177. package/dist/db/seed.js.map +0 -1
  178. package/dist/db/seedOAuth.d.ts +0 -4
  179. package/dist/db/seedOAuth.d.ts.map +0 -1
  180. package/dist/db/seedOAuth.js +0 -76
  181. package/dist/db/seedOAuth.js.map +0 -1
  182. package/dist/governance/config.d.ts +0 -66
  183. package/dist/governance/config.d.ts.map +0 -1
  184. package/dist/governance/config.js +0 -238
  185. package/dist/governance/config.js.map +0 -1
  186. package/dist/governance/detectors/hallucination.d.ts +0 -61
  187. package/dist/governance/detectors/hallucination.d.ts.map +0 -1
  188. package/dist/governance/detectors/hallucination.js +0 -338
  189. package/dist/governance/detectors/hallucination.js.map +0 -1
  190. package/dist/governance/detectors/inconsistency.d.ts +0 -99
  191. package/dist/governance/detectors/inconsistency.d.ts.map +0 -1
  192. package/dist/governance/detectors/inconsistency.js +0 -548
  193. package/dist/governance/detectors/inconsistency.js.map +0 -1
  194. package/dist/governance/detectors/toneDrift.d.ts +0 -63
  195. package/dist/governance/detectors/toneDrift.d.ts.map +0 -1
  196. package/dist/governance/detectors/toneDrift.js +0 -421
  197. package/dist/governance/detectors/toneDrift.js.map +0 -1
  198. package/dist/governance/detectors/unsafeReasoning.d.ts +0 -54
  199. package/dist/governance/detectors/unsafeReasoning.d.ts.map +0 -1
  200. package/dist/governance/detectors/unsafeReasoning.js +0 -473
  201. package/dist/governance/detectors/unsafeReasoning.js.map +0 -1
  202. package/dist/governance/evaluationEngine.d.ts +0 -112
  203. package/dist/governance/evaluationEngine.d.ts.map +0 -1
  204. package/dist/governance/evaluationEngine.js +0 -265
  205. package/dist/governance/evaluationEngine.js.map +0 -1
  206. package/dist/governance/intervention.d.ts +0 -81
  207. package/dist/governance/intervention.d.ts.map +0 -1
  208. package/dist/governance/intervention.js +0 -405
  209. package/dist/governance/intervention.js.map +0 -1
  210. package/dist/server/oauth/anomalyDetection.d.ts +0 -146
  211. package/dist/server/oauth/anomalyDetection.d.ts.map +0 -1
  212. package/dist/server/oauth/anomalyDetection.js +0 -405
  213. package/dist/server/oauth/anomalyDetection.js.map +0 -1
  214. package/dist/server/oauth/authServer.d.ts +0 -61
  215. package/dist/server/oauth/authServer.d.ts.map +0 -1
  216. package/dist/server/oauth/authServer.js +0 -283
  217. package/dist/server/oauth/authServer.js.map +0 -1
  218. package/dist/server/oauth/dpop.d.ts +0 -135
  219. package/dist/server/oauth/dpop.d.ts.map +0 -1
  220. package/dist/server/oauth/dpop.js +0 -338
  221. package/dist/server/oauth/dpop.js.map +0 -1
  222. package/dist/server/oauth/gdpr/consent.d.ts +0 -173
  223. package/dist/server/oauth/gdpr/consent.d.ts.map +0 -1
  224. package/dist/server/oauth/gdpr/consent.js +0 -388
  225. package/dist/server/oauth/gdpr/consent.js.map +0 -1
  226. package/dist/server/oauth/gdpr/dataPortability.d.ts +0 -214
  227. package/dist/server/oauth/gdpr/dataPortability.d.ts.map +0 -1
  228. package/dist/server/oauth/gdpr/dataPortability.js +0 -486
  229. package/dist/server/oauth/gdpr/dataPortability.js.map +0 -1
  230. package/dist/server/oauth/gdpr/index.d.ts +0 -103
  231. package/dist/server/oauth/gdpr/index.d.ts.map +0 -1
  232. package/dist/server/oauth/gdpr/index.js +0 -273
  233. package/dist/server/oauth/gdpr/index.js.map +0 -1
  234. package/dist/server/oauth/gdpr/rightToErasure.d.ts +0 -184
  235. package/dist/server/oauth/gdpr/rightToErasure.d.ts.map +0 -1
  236. package/dist/server/oauth/gdpr/rightToErasure.js +0 -527
  237. package/dist/server/oauth/gdpr/rightToErasure.js.map +0 -1
  238. package/dist/server/oauth/monitoring/securityMonitor.d.ts +0 -218
  239. package/dist/server/oauth/monitoring/securityMonitor.d.ts.map +0 -1
  240. package/dist/server/oauth/monitoring/securityMonitor.js +0 -615
  241. package/dist/server/oauth/monitoring/securityMonitor.js.map +0 -1
  242. package/dist/server/oauth/pkce.d.ts +0 -61
  243. package/dist/server/oauth/pkce.d.ts.map +0 -1
  244. package/dist/server/oauth/pkce.js +0 -157
  245. package/dist/server/oauth/pkce.js.map +0 -1
  246. package/dist/server/oauth/providers/base.d.ts +0 -147
  247. package/dist/server/oauth/providers/base.d.ts.map +0 -1
  248. package/dist/server/oauth/providers/base.js +0 -312
  249. package/dist/server/oauth/providers/base.js.map +0 -1
  250. package/dist/server/oauth/providers/github.d.ts +0 -55
  251. package/dist/server/oauth/providers/github.d.ts.map +0 -1
  252. package/dist/server/oauth/providers/github.js +0 -225
  253. package/dist/server/oauth/providers/github.js.map +0 -1
  254. package/dist/server/oauth/providers/google.d.ts +0 -49
  255. package/dist/server/oauth/providers/google.d.ts.map +0 -1
  256. package/dist/server/oauth/providers/google.js +0 -153
  257. package/dist/server/oauth/providers/google.js.map +0 -1
  258. package/dist/server/oauth/providers/index.d.ts +0 -9
  259. package/dist/server/oauth/providers/index.d.ts.map +0 -1
  260. package/dist/server/oauth/providers/index.js +0 -24
  261. package/dist/server/oauth/providers/index.js.map +0 -1
  262. package/dist/server/oauth/refreshTokenRotation.d.ts +0 -114
  263. package/dist/server/oauth/refreshTokenRotation.d.ts.map +0 -1
  264. package/dist/server/oauth/refreshTokenRotation.js +0 -344
  265. package/dist/server/oauth/refreshTokenRotation.js.map +0 -1
  266. package/dist/server/oauth/security.d.ts +0 -101
  267. package/dist/server/oauth/security.d.ts.map +0 -1
  268. package/dist/server/oauth/security.js +0 -268
  269. package/dist/server/oauth/security.js.map +0 -1
  270. package/dist/server/oauth/tokenEncryption.d.ts +0 -80
  271. package/dist/server/oauth/tokenEncryption.d.ts.map +0 -1
  272. package/dist/server/oauth/tokenEncryption.js +0 -218
  273. package/dist/server/oauth/tokenEncryption.js.map +0 -1
  274. package/dist/tools/sendMessage-complex-backup.d.ts +0 -6
  275. package/dist/tools/sendMessage-complex-backup.d.ts.map +0 -1
  276. package/dist/tools/sendMessage-complex-backup.js +0 -545
  277. package/dist/tools/sendMessage-complex-backup.js.map +0 -1
  278. package/dist/tools/sendMessage-revised.d.ts +0 -11
  279. package/dist/tools/sendMessage-revised.d.ts.map +0 -1
  280. package/dist/tools/sendMessage-revised.js +0 -429
  281. package/dist/tools/sendMessage-revised.js.map +0 -1
  282. package/dist/tools/sendMessage-truly-simple.d.ts +0 -8
  283. package/dist/tools/sendMessage-truly-simple.d.ts.map +0 -1
  284. package/dist/tools/sendMessage-truly-simple.js +0 -299
  285. package/dist/tools/sendMessage-truly-simple.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../../src/server/oauth/providers/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAGnF;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,gBAAgB,kDAAkD;IAC3E,QAAQ,CAAC,QAAQ,yCAAyC;IAC1D,QAAQ,CAAC,WAAW,mDAAmD;IACvE,QAAQ,CAAC,SAAS,0CAA0C;IAC5D,QAAQ,CAAC,OAAO,gDAAgD;gBAEpD,MAAM,EAAE,cAAc;IAsBlC;;OAEG;IACH,SAAS,CAAC,gBAAgB,IAAI,MAAM,EAAE;IAWtC;;OAEG;IACH,SAAS,CAAC,iBAAiB,IAAI,MAAM;IAIrC;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG,QAAQ;IAahD;;OAEG;IACH,SAAS,CAAC,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAe5D;;;OAGG;IACG,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IASjE;;OAEG;IACG,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,GACtC,OAAO,CAAC,OAAO,CAAC;IAoBnB;;;OAGG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,cAAc,GAAG,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB7F;;OAEG;IACH,SAAS,CAAC,mBAAmB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK;CAYjD"}
@@ -1,153 +0,0 @@
1
- import { OAuthProvider } from './base.js';
2
- import { logger } from '../../../utils/logger.js';
3
- /**
4
- * Google OAuth 2.0 Provider
5
- * Implements Google Sign-In with OpenID Connect
6
- */
7
- export class GoogleOAuthProvider extends OAuthProvider {
8
- name = 'google';
9
- authorizationUrl = 'https://accounts.google.com/o/oauth2/v2/auth';
10
- tokenUrl = 'https://oauth2.googleapis.com/token';
11
- userInfoUrl = 'https://www.googleapis.com/oauth2/v2/userinfo';
12
- revokeUrl = 'https://oauth2.googleapis.com/revoke';
13
- jwksUrl = 'https://www.googleapis.com/oauth2/v3/certs';
14
- constructor(config) {
15
- super(config);
16
- // Set Google-specific defaults
17
- if (!this.config.scopes || this.config.scopes.length === 0) {
18
- this.config.scopes = this.getDefaultScopes();
19
- }
20
- // Google-specific additional parameters
21
- if (!this.config.additionalParams) {
22
- this.config.additionalParams = {};
23
- }
24
- // Request refresh token
25
- this.config.additionalParams.access_type = 'offline';
26
- // Force approval prompt for refresh token on first auth
27
- if (process.env.GOOGLE_FORCE_APPROVAL === 'true') {
28
- this.config.additionalParams.prompt = 'consent';
29
- }
30
- }
31
- /**
32
- * Get default scopes for Google
33
- */
34
- getDefaultScopes() {
35
- return [
36
- 'openid',
37
- 'email',
38
- 'profile',
39
- // Add additional scopes as needed
40
- // 'https://www.googleapis.com/auth/calendar.readonly',
41
- // 'https://www.googleapis.com/auth/drive.file',
42
- ];
43
- }
44
- /**
45
- * Get expected issuer for Google
46
- */
47
- getExpectedIssuer() {
48
- return 'https://accounts.google.com';
49
- }
50
- /**
51
- * Normalize Google user info to common format
52
- */
53
- normalizeUserInfo(data) {
54
- return {
55
- id: data.id || data.sub,
56
- email: data.email,
57
- email_verified: data.email_verified || data.verified_email,
58
- name: data.name,
59
- picture: data.picture,
60
- locale: data.locale,
61
- provider: this.name,
62
- raw: data,
63
- };
64
- }
65
- /**
66
- * Additional Google-specific ID token validation
67
- */
68
- validateIdTokenClaims(claims) {
69
- super.validateIdTokenClaims(claims);
70
- // Google-specific: Check HD claim for G Suite domains
71
- const allowedDomain = process.env.GOOGLE_ALLOWED_DOMAIN;
72
- if (allowedDomain && claims.hd !== allowedDomain) {
73
- throw new Error(`User not from allowed domain: ${allowedDomain}`);
74
- }
75
- // Verify email is verified for Google accounts
76
- if (claims.email && !claims.email_verified) {
77
- throw new Error('Email not verified');
78
- }
79
- }
80
- /**
81
- * Google-specific user info enrichment
82
- * Can fetch additional profile data if needed
83
- */
84
- async getEnrichedUserInfo(accessToken) {
85
- const baseInfo = await this.getUserInfo(accessToken);
86
- // Could fetch additional Google APIs data here
87
- // For example: Google+ profile, Calendar info, etc.
88
- return baseInfo;
89
- }
90
- /**
91
- * Check if user has specific Google service access
92
- */
93
- async checkServiceAccess(accessToken, service) {
94
- const serviceUrls = {
95
- calendar: 'https://www.googleapis.com/calendar/v3/users/me/settings',
96
- drive: 'https://www.googleapis.com/drive/v3/about',
97
- gmail: 'https://www.googleapis.com/gmail/v1/users/me/profile',
98
- };
99
- try {
100
- const response = await fetch(serviceUrls[service], {
101
- headers: {
102
- 'Authorization': `Bearer ${accessToken}`,
103
- },
104
- });
105
- return response.ok;
106
- }
107
- catch {
108
- return false;
109
- }
110
- }
111
- /**
112
- * Revoke Google tokens
113
- * Google supports revoking both access and refresh tokens
114
- */
115
- async revokeToken(token, tokenType) {
116
- // Google revokes all tokens associated with the grant
117
- const params = new URLSearchParams({ token });
118
- try {
119
- const response = await fetch(this.revokeUrl, {
120
- method: 'POST',
121
- headers: {
122
- 'Content-Type': 'application/x-www-form-urlencoded',
123
- },
124
- body: params.toString(),
125
- });
126
- if (response.ok) {
127
- logger.info('Successfully revoked Google tokens');
128
- }
129
- else {
130
- const error = await response.text();
131
- logger.error(`Failed to revoke Google token: ${error}`);
132
- }
133
- }
134
- catch (error) {
135
- logger.error('Error revoking Google token:', error);
136
- throw error;
137
- }
138
- }
139
- /**
140
- * Handle Google-specific errors
141
- */
142
- handleProviderError(error) {
143
- // Handle Google-specific error codes
144
- if (error.error === 'invalid_grant') {
145
- throw new Error('Authorization code has been used or is invalid');
146
- }
147
- if (error.error === 'access_denied') {
148
- throw new Error('User denied access to Google account');
149
- }
150
- throw error;
151
- }
152
- }
153
- //# sourceMappingURL=google.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"google.js","sourceRoot":"","sources":["../../../../src/server/oauth/providers/google.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Register all available OAuth providers
3
- */
4
- export declare function registerProviders(): void;
5
- export { ProviderFactory } from './base.js';
6
- export { GoogleOAuthProvider } from './google.js';
7
- export { GitHubOAuthProvider } from './github.js';
8
- export type { OAuthProvider, TokenResponse, UserInfo, IdTokenClaims, ProviderConfig, } from './base.js';
9
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/oauth/providers/index.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAYxC;AAMD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EACV,aAAa,EACb,aAAa,EACb,QAAQ,EACR,aAAa,EACb,cAAc,GACf,MAAM,WAAW,CAAC"}
@@ -1,24 +0,0 @@
1
- import { ProviderFactory } from './base.js';
2
- import { GoogleOAuthProvider } from './google.js';
3
- import { GitHubOAuthProvider } from './github.js';
4
- import { logger } from '../../../utils/logger.js';
5
- /**
6
- * Register all available OAuth providers
7
- */
8
- export function registerProviders() {
9
- // Register Google
10
- ProviderFactory.register('google', GoogleOAuthProvider);
11
- // Register GitHub
12
- ProviderFactory.register('github', GitHubOAuthProvider);
13
- // Additional providers can be registered here
14
- // ProviderFactory.register('microsoft', MicrosoftOAuthProvider);
15
- // ProviderFactory.register('apple', AppleOAuthProvider);
16
- logger.info(`Registered ${ProviderFactory.getProviders().length} OAuth providers`);
17
- }
18
- // Auto-register on module load
19
- registerProviders();
20
- // Export all providers and factory
21
- export { ProviderFactory } from './base.js';
22
- export { GoogleOAuthProvider } from './google.js';
23
- export { GitHubOAuthProvider } from './github.js';
24
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/oauth/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAElD;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,kBAAkB;IAClB,eAAe,CAAC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IAExD,kBAAkB;IAClB,eAAe,CAAC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IAExD,8CAA8C;IAC9C,iEAAiE;IACjE,yDAAyD;IAEzD,MAAM,CAAC,IAAI,CAAC,cAAc,eAAe,CAAC,YAAY,EAAE,CAAC,MAAM,kBAAkB,CAAC,CAAC;AACrF,CAAC;AAED,+BAA+B;AAC/B,iBAAiB,EAAE,CAAC;AAEpB,mCAAmC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -1,114 +0,0 @@
1
- /**
2
- * Token family for tracking refresh token lineage
3
- */
4
- export interface TokenFamily {
5
- familyId: string;
6
- currentTokenHash: string;
7
- previousTokenHashes: string[];
8
- userId: string;
9
- clientId: string;
10
- createdAt: Date;
11
- lastRotated: Date;
12
- rotationCount: number;
13
- metadata?: {
14
- ipAddress?: string;
15
- userAgent?: string;
16
- deviceId?: string;
17
- };
18
- }
19
- /**
20
- * Token rotation result
21
- */
22
- export interface TokenRotationResult {
23
- accessToken: string;
24
- refreshToken: string;
25
- expiresIn: number;
26
- tokenType: 'Bearer';
27
- }
28
- /**
29
- * Security event types for monitoring
30
- */
31
- export declare enum SecurityEvent {
32
- TOKEN_ROTATED = "token_rotated",
33
- TOKEN_REUSE_DETECTED = "token_reuse_detected",
34
- TOKEN_FAMILY_REVOKED = "family_revoked",
35
- SUSPICIOUS_ROTATION = "suspicious_rotation"
36
- }
37
- /**
38
- * Refresh Token Manager with rotation support
39
- * Implements automatic token rotation and reuse detection
40
- */
41
- export declare class RefreshTokenManager {
42
- private tokenFamilies;
43
- private readonly ACCESS_TOKEN_TTL;
44
- private readonly REFRESH_TOKEN_TTL;
45
- private readonly MAX_ROTATION_COUNT;
46
- private readonly REUSE_DETECTION_WINDOW;
47
- /**
48
- * Generate a new token family for initial authentication
49
- */
50
- createTokenFamily(userId: string, clientId: string, metadata?: TokenFamily['metadata']): Promise<TokenRotationResult>;
51
- /**
52
- * Rotate refresh token
53
- * Detects and prevents token reuse attacks
54
- */
55
- rotateRefreshToken(oldRefreshToken: string, metadata?: TokenFamily['metadata']): Promise<TokenRotationResult>;
56
- /**
57
- * Check if token has been reused
58
- * Allows small grace period for legitimate retries
59
- */
60
- private isTokenReused;
61
- /**
62
- * Handle token reuse detection
63
- * Revokes entire token family as a security measure
64
- */
65
- private handleTokenReuse;
66
- /**
67
- * Revoke an entire token family
68
- * Used when token reuse or other attacks are detected
69
- */
70
- revokeTokenFamily(familyId: string): Promise<void>;
71
- /**
72
- * Revoke all tokens for a user
73
- * Used in case of account compromise
74
- */
75
- revokeAllUserTokens(userId: string): Promise<void>;
76
- /**
77
- * Find token family by refresh token hash
78
- */
79
- private findTokenFamily;
80
- /**
81
- * Detect suspicious rotation patterns
82
- */
83
- private detectSuspiciousRotation;
84
- /**
85
- * Generate new refresh token
86
- */
87
- private generateRefreshToken;
88
- /**
89
- * Generate new access token (JWT)
90
- */
91
- private generateAccessToken;
92
- /**
93
- * Persist token family to database
94
- */
95
- private persistTokenFamily;
96
- /**
97
- * Update token family in database
98
- */
99
- private updateTokenFamily;
100
- /**
101
- * Log security event
102
- */
103
- private logSecurityEvent;
104
- /**
105
- * Notify security team of critical events
106
- */
107
- private notifySecurityTeam;
108
- /**
109
- * Clean up expired token families
110
- */
111
- cleanupExpiredFamilies(): Promise<void>;
112
- }
113
- export declare const refreshTokenManager: RefreshTokenManager;
114
- //# sourceMappingURL=refreshTokenRotation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refreshTokenRotation.d.ts","sourceRoot":"","sources":["../../../src/server/oauth/refreshTokenRotation.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,WAAW,EAAE,IAAI,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE;QACT,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,QAAQ,CAAC;CACrB;AAED;;GAEG;AACH,oBAAY,aAAa;IACvB,aAAa,kBAAkB;IAC/B,oBAAoB,yBAAyB;IAC7C,oBAAoB,mBAAmB;IACvC,mBAAmB,wBAAwB;CAC5C;AAED;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmD;IACpF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAwD;IAC1F,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IAC1C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAE/C;;OAEG;IACG,iBAAiB,CACrB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,GACjC,OAAO,CAAC,mBAAmB,CAAC;IAkC/B;;;OAGG;IACG,kBAAkB,CACtB,eAAe,EAAE,MAAM,EACvB,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,GACjC,OAAO,CAAC,mBAAmB,CAAC;IAiE/B;;;OAGG;YACW,aAAa;IAoB3B;;;OAGG;YACW,gBAAgB;IAM9B;;;OAGG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBxD;;;OAGG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBxD;;OAEG;YACW,eAAe;IAsD7B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA2BhC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;YACW,mBAAmB;IAajC;;OAEG;YACW,kBAAkB;IAuBhC;;OAEG;YACW,iBAAiB;IAqB/B;;OAEG;YACW,gBAAgB;IAQ9B;;OAEG;YACW,kBAAkB;IAKhC;;OAEG;IACG,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;CAkB9C;AAGD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC"}
@@ -1,344 +0,0 @@
1
- import { randomBytes } from 'crypto';
2
- import { logger } from '../../utils/logger.js';
3
- import { getDb } from '../../db/client.js';
4
- import { oauthTokens } from '../../db/schema.js';
5
- import { eq, and, isNull } from 'drizzle-orm';
6
- import { tokenEncryption } from './tokenEncryption.js';
7
- import jwt from 'jsonwebtoken';
8
- /**
9
- * Security event types for monitoring
10
- */
11
- export var SecurityEvent;
12
- (function (SecurityEvent) {
13
- SecurityEvent["TOKEN_ROTATED"] = "token_rotated";
14
- SecurityEvent["TOKEN_REUSE_DETECTED"] = "token_reuse_detected";
15
- SecurityEvent["TOKEN_FAMILY_REVOKED"] = "family_revoked";
16
- SecurityEvent["SUSPICIOUS_ROTATION"] = "suspicious_rotation";
17
- })(SecurityEvent || (SecurityEvent = {}));
18
- /**
19
- * Refresh Token Manager with rotation support
20
- * Implements automatic token rotation and reuse detection
21
- */
22
- export class RefreshTokenManager {
23
- tokenFamilies = new Map();
24
- ACCESS_TOKEN_TTL = parseInt(process.env.ACCESS_TOKEN_TTL || '900'); // 15 minutes
25
- REFRESH_TOKEN_TTL = parseInt(process.env.REFRESH_TOKEN_TTL || '2592000'); // 30 days
26
- MAX_ROTATION_COUNT = 100; // Prevent infinite rotation
27
- REUSE_DETECTION_WINDOW = 2000; // 2 seconds grace period
28
- /**
29
- * Generate a new token family for initial authentication
30
- */
31
- async createTokenFamily(userId, clientId, metadata) {
32
- const familyId = randomBytes(16).toString('base64url');
33
- const refreshToken = this.generateRefreshToken();
34
- const refreshTokenHash = tokenEncryption.hashToken(refreshToken);
35
- const family = {
36
- familyId,
37
- currentTokenHash: refreshTokenHash,
38
- previousTokenHashes: [],
39
- userId,
40
- clientId,
41
- createdAt: new Date(),
42
- lastRotated: new Date(),
43
- rotationCount: 0,
44
- metadata,
45
- };
46
- // Store family in memory and database
47
- this.tokenFamilies.set(familyId, family);
48
- await this.persistTokenFamily(family, refreshToken);
49
- // Generate access token
50
- const accessToken = await this.generateAccessToken(userId, clientId);
51
- logger.info(`Created new token family ${familyId} for user ${userId}`);
52
- return {
53
- accessToken,
54
- refreshToken,
55
- expiresIn: this.ACCESS_TOKEN_TTL,
56
- tokenType: 'Bearer',
57
- };
58
- }
59
- /**
60
- * Rotate refresh token
61
- * Detects and prevents token reuse attacks
62
- */
63
- async rotateRefreshToken(oldRefreshToken, metadata) {
64
- const oldTokenHash = tokenEncryption.hashToken(oldRefreshToken);
65
- // Find token family
66
- const family = await this.findTokenFamily(oldTokenHash);
67
- if (!family) {
68
- logger.error('Refresh token not found - possible attack');
69
- throw new Error('Invalid refresh token');
70
- }
71
- // Check for token reuse (replay attack)
72
- if (await this.isTokenReused(family, oldTokenHash)) {
73
- logger.error(`Token reuse detected for family ${family.familyId}`);
74
- await this.handleTokenReuse(family);
75
- throw new Error('Token reuse detected - all tokens revoked');
76
- }
77
- // Check rotation count to prevent infinite rotation
78
- if (family.rotationCount >= this.MAX_ROTATION_COUNT) {
79
- logger.warn(`Max rotation count reached for family ${family.familyId}`);
80
- await this.revokeTokenFamily(family.familyId);
81
- throw new Error('Maximum token rotations exceeded');
82
- }
83
- // Check for suspicious rotation patterns
84
- if (this.detectSuspiciousRotation(family, metadata)) {
85
- logger.warn(`Suspicious rotation pattern detected for family ${family.familyId}`);
86
- await this.logSecurityEvent(SecurityEvent.SUSPICIOUS_ROTATION, family);
87
- }
88
- // Generate new tokens
89
- const newRefreshToken = this.generateRefreshToken();
90
- const newRefreshTokenHash = tokenEncryption.hashToken(newRefreshToken);
91
- const newAccessToken = await this.generateAccessToken(family.userId, family.clientId);
92
- // Update token family
93
- family.previousTokenHashes.push(family.currentTokenHash);
94
- family.currentTokenHash = newRefreshTokenHash;
95
- family.lastRotated = new Date();
96
- family.rotationCount++;
97
- // Limit history to prevent memory bloat (keep last 10)
98
- if (family.previousTokenHashes.length > 10) {
99
- family.previousTokenHashes = family.previousTokenHashes.slice(-10);
100
- }
101
- // Update metadata if provided
102
- if (metadata) {
103
- family.metadata = { ...family.metadata, ...metadata };
104
- }
105
- // Persist changes
106
- await this.updateTokenFamily(family, newRefreshToken, oldRefreshToken);
107
- logger.info(`Rotated refresh token for family ${family.familyId}, rotation #${family.rotationCount}`);
108
- return {
109
- accessToken: newAccessToken,
110
- refreshToken: newRefreshToken,
111
- expiresIn: this.ACCESS_TOKEN_TTL,
112
- tokenType: 'Bearer',
113
- };
114
- }
115
- /**
116
- * Check if token has been reused
117
- * Allows small grace period for legitimate retries
118
- */
119
- async isTokenReused(family, tokenHash) {
120
- // Current token is valid
121
- if (tokenHash === family.currentTokenHash) {
122
- return false;
123
- }
124
- // Check if it's a recently rotated token (within grace period)
125
- const timeSinceRotation = Date.now() - family.lastRotated.getTime();
126
- if (timeSinceRotation < this.REUSE_DETECTION_WINDOW) {
127
- const lastPrevious = family.previousTokenHashes[family.previousTokenHashes.length - 1];
128
- if (tokenHash === lastPrevious) {
129
- logger.debug('Token use within grace period, allowing');
130
- return false;
131
- }
132
- }
133
- // Check if it's an old token (definite reuse)
134
- return family.previousTokenHashes.includes(tokenHash);
135
- }
136
- /**
137
- * Handle token reuse detection
138
- * Revokes entire token family as a security measure
139
- */
140
- async handleTokenReuse(family) {
141
- await this.logSecurityEvent(SecurityEvent.TOKEN_REUSE_DETECTED, family);
142
- await this.revokeTokenFamily(family.familyId);
143
- await this.notifySecurityTeam(family);
144
- }
145
- /**
146
- * Revoke an entire token family
147
- * Used when token reuse or other attacks are detected
148
- */
149
- async revokeTokenFamily(familyId) {
150
- const family = this.tokenFamilies.get(familyId);
151
- if (!family) {
152
- return;
153
- }
154
- const db = getDb();
155
- // Mark all tokens in family as revoked
156
- await db.update(oauthTokens)
157
- .set({
158
- revokedAt: new Date(),
159
- revocationReason: 'family_revoked',
160
- })
161
- .where(eq(oauthTokens.tokenFamilyId, familyId));
162
- // Remove from memory
163
- this.tokenFamilies.delete(familyId);
164
- logger.info(`Revoked token family ${familyId} for user ${family.userId}`);
165
- await this.logSecurityEvent(SecurityEvent.TOKEN_FAMILY_REVOKED, family);
166
- }
167
- /**
168
- * Revoke all tokens for a user
169
- * Used in case of account compromise
170
- */
171
- async revokeAllUserTokens(userId) {
172
- const db = getDb();
173
- // Revoke all tokens
174
- await db.update(oauthTokens)
175
- .set({
176
- revokedAt: new Date(),
177
- revocationReason: 'user_revoked_all',
178
- })
179
- .where(eq(oauthTokens.userId, userId));
180
- // Remove from memory
181
- for (const [familyId, family] of this.tokenFamilies.entries()) {
182
- if (family.userId === userId) {
183
- this.tokenFamilies.delete(familyId);
184
- }
185
- }
186
- logger.info(`Revoked all tokens for user ${userId}`);
187
- }
188
- /**
189
- * Find token family by refresh token hash
190
- */
191
- async findTokenFamily(tokenHash) {
192
- // Check memory cache first
193
- for (const family of this.tokenFamilies.values()) {
194
- if (family.currentTokenHash === tokenHash ||
195
- family.previousTokenHashes.includes(tokenHash)) {
196
- return family;
197
- }
198
- }
199
- // Check database
200
- const db = getDb();
201
- const result = await db.select()
202
- .from(oauthTokens)
203
- .where(and(eq(oauthTokens.refreshTokenHash, tokenHash), isNull(oauthTokens.revokedAt)))
204
- .limit(1);
205
- if (result.length === 0) {
206
- return null;
207
- }
208
- // Reconstruct family from database
209
- const token = result[0];
210
- // Handle nullable fields
211
- if (!token || !token.tokenFamilyId || !token.refreshTokenHash || !token.clientId) {
212
- return null;
213
- }
214
- const family = {
215
- familyId: token.tokenFamilyId,
216
- currentTokenHash: token.refreshTokenHash,
217
- previousTokenHashes: [], // Would need separate table for full history
218
- userId: token.userId,
219
- clientId: token.clientId,
220
- createdAt: token.createdAt,
221
- lastRotated: token.createdAt,
222
- rotationCount: 0,
223
- metadata: {
224
- ipAddress: token.ipAddress || undefined,
225
- userAgent: token.userAgent || undefined,
226
- },
227
- };
228
- // Cache in memory
229
- this.tokenFamilies.set(family.familyId, family);
230
- return family;
231
- }
232
- /**
233
- * Detect suspicious rotation patterns
234
- */
235
- detectSuspiciousRotation(family, newMetadata) {
236
- // Rapid rotation (more than once per minute)
237
- const timeSinceLastRotation = Date.now() - family.lastRotated.getTime();
238
- if (timeSinceLastRotation < 60000) {
239
- return true;
240
- }
241
- // Different IP address
242
- if (newMetadata?.ipAddress &&
243
- family.metadata?.ipAddress &&
244
- newMetadata.ipAddress !== family.metadata.ipAddress) {
245
- return true;
246
- }
247
- // Different device
248
- if (newMetadata?.deviceId &&
249
- family.metadata?.deviceId &&
250
- newMetadata.deviceId !== family.metadata.deviceId) {
251
- return true;
252
- }
253
- return false;
254
- }
255
- /**
256
- * Generate new refresh token
257
- */
258
- generateRefreshToken() {
259
- return randomBytes(32).toString('base64url');
260
- }
261
- /**
262
- * Generate new access token (JWT)
263
- */
264
- async generateAccessToken(userId, clientId) {
265
- const payload = {
266
- sub: userId,
267
- client_id: clientId,
268
- token_type: 'access',
269
- iat: Math.floor(Date.now() / 1000),
270
- exp: Math.floor(Date.now() / 1000) + this.ACCESS_TOKEN_TTL,
271
- };
272
- const secret = process.env.JWT_SECRET || 'dev-secret-change-in-production';
273
- return jwt.sign(payload, secret, { algorithm: 'HS256' });
274
- }
275
- /**
276
- * Persist token family to database
277
- */
278
- async persistTokenFamily(family, refreshToken) {
279
- const db = getDb();
280
- const encryptedToken = await tokenEncryption.encryptToken(refreshToken);
281
- await db.insert(oauthTokens)
282
- .values({
283
- userId: family.userId,
284
- clientId: family.clientId,
285
- tokenFamilyId: family.familyId,
286
- refreshTokenHash: family.currentTokenHash,
287
- refreshTokenEncrypted: encryptedToken.encrypted,
288
- accessTokenHash: '', // Will be set separately
289
- accessTokenEncrypted: '', // Will be set separately
290
- scope: 'default',
291
- expiresAt: new Date(Date.now() + this.REFRESH_TOKEN_TTL * 1000),
292
- ipAddress: family.metadata?.ipAddress,
293
- userAgent: family.metadata?.userAgent,
294
- });
295
- }
296
- /**
297
- * Update token family in database
298
- */
299
- async updateTokenFamily(family, newRefreshToken, oldRefreshToken) {
300
- const db = getDb();
301
- const encryptedToken = await tokenEncryption.encryptToken(newRefreshToken);
302
- const oldTokenHash = tokenEncryption.hashToken(oldRefreshToken);
303
- // Mark old token as rotated
304
- await db.update(oauthTokens)
305
- .set({
306
- revokedAt: new Date(),
307
- revocationReason: 'rotated',
308
- })
309
- .where(eq(oauthTokens.refreshTokenHash, oldTokenHash));
310
- // Insert new token
311
- await this.persistTokenFamily(family, newRefreshToken);
312
- }
313
- /**
314
- * Log security event
315
- */
316
- async logSecurityEvent(event, family) {
317
- logger.warn(`Security event: ${event} for family ${family.familyId}, user ${family.userId}`);
318
- // TODO: Log to audit table
319
- }
320
- /**
321
- * Notify security team of critical events
322
- */
323
- async notifySecurityTeam(family) {
324
- // TODO: Send alert to security team
325
- logger.error(`SECURITY ALERT: Token reuse detected for user ${family.userId}`);
326
- }
327
- /**
328
- * Clean up expired token families
329
- */
330
- async cleanupExpiredFamilies() {
331
- const db = getDb();
332
- const expiredDate = new Date(Date.now() - this.REFRESH_TOKEN_TTL * 1000);
333
- await db.update(oauthTokens)
334
- .set({
335
- revokedAt: new Date(),
336
- revocationReason: 'expired',
337
- })
338
- .where(and(eq(oauthTokens.revokedAt, null), eq(oauthTokens.expiresAt, expiredDate)));
339
- logger.debug('Cleaned up expired token families');
340
- }
341
- }
342
- // Export singleton instance
343
- export const refreshTokenManager = new RefreshTokenManager();
344
- //# sourceMappingURL=refreshTokenRotation.js.map