@portaidentity/server 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (742) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +21 -0
  3. package/README.md +33 -0
  4. package/dist/applications/cache.d.ts +64 -0
  5. package/dist/applications/cache.d.ts.map +1 -0
  6. package/dist/applications/cache.js +161 -0
  7. package/dist/applications/cache.js.map +1 -0
  8. package/dist/applications/errors.d.ts +25 -0
  9. package/dist/applications/errors.d.ts.map +1 -0
  10. package/dist/applications/errors.js +31 -0
  11. package/dist/applications/errors.js.map +1 -0
  12. package/dist/applications/index.d.ts +17 -0
  13. package/dist/applications/index.d.ts.map +1 -0
  14. package/dist/applications/index.js +19 -0
  15. package/dist/applications/index.js.map +1 -0
  16. package/dist/applications/repository.d.ts +184 -0
  17. package/dist/applications/repository.d.ts.map +1 -0
  18. package/dist/applications/repository.js +367 -0
  19. package/dist/applications/repository.js.map +1 -0
  20. package/dist/applications/service.d.ts +160 -0
  21. package/dist/applications/service.d.ts.map +1 -0
  22. package/dist/applications/service.js +388 -0
  23. package/dist/applications/service.js.map +1 -0
  24. package/dist/applications/slugs.d.ts +61 -0
  25. package/dist/applications/slugs.d.ts.map +1 -0
  26. package/dist/applications/slugs.js +115 -0
  27. package/dist/applications/slugs.js.map +1 -0
  28. package/dist/applications/types.d.ts +129 -0
  29. package/dist/applications/types.d.ts.map +1 -0
  30. package/dist/applications/types.js +62 -0
  31. package/dist/applications/types.js.map +1 -0
  32. package/dist/auth/csrf.d.ts +71 -0
  33. package/dist/auth/csrf.d.ts.map +1 -0
  34. package/dist/auth/csrf.js +112 -0
  35. package/dist/auth/csrf.js.map +1 -0
  36. package/dist/auth/email-renderer.d.ts +37 -0
  37. package/dist/auth/email-renderer.d.ts.map +1 -0
  38. package/dist/auth/email-renderer.js +116 -0
  39. package/dist/auth/email-renderer.js.map +1 -0
  40. package/dist/auth/email-service.d.ts +154 -0
  41. package/dist/auth/email-service.d.ts.map +1 -0
  42. package/dist/auth/email-service.js +415 -0
  43. package/dist/auth/email-service.js.map +1 -0
  44. package/dist/auth/email-transport.d.ts +65 -0
  45. package/dist/auth/email-transport.d.ts.map +1 -0
  46. package/dist/auth/email-transport.js +82 -0
  47. package/dist/auth/email-transport.js.map +1 -0
  48. package/dist/auth/i18n.d.ts +81 -0
  49. package/dist/auth/i18n.d.ts.map +1 -0
  50. package/dist/auth/i18n.js +395 -0
  51. package/dist/auth/i18n.js.map +1 -0
  52. package/dist/auth/index.d.ts +28 -0
  53. package/dist/auth/index.d.ts.map +1 -0
  54. package/dist/auth/index.js +31 -0
  55. package/dist/auth/index.js.map +1 -0
  56. package/dist/auth/interaction-authority.d.ts +39 -0
  57. package/dist/auth/interaction-authority.d.ts.map +1 -0
  58. package/dist/auth/interaction-authority.js +30 -0
  59. package/dist/auth/interaction-authority.js.map +1 -0
  60. package/dist/auth/magic-link-session.d.ts +81 -0
  61. package/dist/auth/magic-link-session.d.ts.map +1 -0
  62. package/dist/auth/magic-link-session.js +183 -0
  63. package/dist/auth/magic-link-session.js.map +1 -0
  64. package/dist/auth/rate-limiter.d.ts +143 -0
  65. package/dist/auth/rate-limiter.d.ts.map +1 -0
  66. package/dist/auth/rate-limiter.js +220 -0
  67. package/dist/auth/rate-limiter.js.map +1 -0
  68. package/dist/auth/recovery-crypto.d.ts +34 -0
  69. package/dist/auth/recovery-crypto.d.ts.map +1 -0
  70. package/dist/auth/recovery-crypto.js +103 -0
  71. package/dist/auth/recovery-crypto.js.map +1 -0
  72. package/dist/auth/recovery-job-processor.d.ts +24 -0
  73. package/dist/auth/recovery-job-processor.d.ts.map +1 -0
  74. package/dist/auth/recovery-job-processor.js +123 -0
  75. package/dist/auth/recovery-job-processor.js.map +1 -0
  76. package/dist/auth/recovery-job-repository.d.ts +219 -0
  77. package/dist/auth/recovery-job-repository.d.ts.map +1 -0
  78. package/dist/auth/recovery-job-repository.js +340 -0
  79. package/dist/auth/recovery-job-repository.js.map +1 -0
  80. package/dist/auth/recovery-service.d.ts +27 -0
  81. package/dist/auth/recovery-service.d.ts.map +1 -0
  82. package/dist/auth/recovery-service.js +53 -0
  83. package/dist/auth/recovery-service.js.map +1 -0
  84. package/dist/auth/recovery-worker.d.ts +158 -0
  85. package/dist/auth/recovery-worker.d.ts.map +1 -0
  86. package/dist/auth/recovery-worker.js +306 -0
  87. package/dist/auth/recovery-worker.js.map +1 -0
  88. package/dist/auth/template-engine.d.ts +134 -0
  89. package/dist/auth/template-engine.d.ts.map +1 -0
  90. package/dist/auth/template-engine.js +225 -0
  91. package/dist/auth/template-engine.js.map +1 -0
  92. package/dist/auth/token-repository.d.ts +238 -0
  93. package/dist/auth/token-repository.d.ts.map +1 -0
  94. package/dist/auth/token-repository.js +475 -0
  95. package/dist/auth/token-repository.js.map +1 -0
  96. package/dist/auth/tokens.d.ts +45 -0
  97. package/dist/auth/tokens.d.ts.map +1 -0
  98. package/dist/auth/tokens.js +51 -0
  99. package/dist/auth/tokens.js.map +1 -0
  100. package/dist/cli/bootstrap.d.ts +55 -0
  101. package/dist/cli/bootstrap.d.ts.map +1 -0
  102. package/dist/cli/bootstrap.js +90 -0
  103. package/dist/cli/bootstrap.js.map +1 -0
  104. package/dist/cli/commands/health.d.ts +20 -0
  105. package/dist/cli/commands/health.d.ts.map +1 -0
  106. package/dist/cli/commands/health.js +80 -0
  107. package/dist/cli/commands/health.js.map +1 -0
  108. package/dist/cli/commands/init.d.ts +48 -0
  109. package/dist/cli/commands/init.d.ts.map +1 -0
  110. package/dist/cli/commands/init.js +349 -0
  111. package/dist/cli/commands/init.js.map +1 -0
  112. package/dist/cli/commands/migrate.d.ts +19 -0
  113. package/dist/cli/commands/migrate.d.ts.map +1 -0
  114. package/dist/cli/commands/migrate.js +88 -0
  115. package/dist/cli/commands/migrate.js.map +1 -0
  116. package/dist/cli/commands/seed.d.ts +19 -0
  117. package/dist/cli/commands/seed.d.ts.map +1 -0
  118. package/dist/cli/commands/seed.js +71 -0
  119. package/dist/cli/commands/seed.js.map +1 -0
  120. package/dist/cli/commands/user-2fa.d.ts +29 -0
  121. package/dist/cli/commands/user-2fa.d.ts.map +1 -0
  122. package/dist/cli/commands/user-2fa.js +113 -0
  123. package/dist/cli/commands/user-2fa.js.map +1 -0
  124. package/dist/cli/error-handler.d.ts +31 -0
  125. package/dist/cli/error-handler.d.ts.map +1 -0
  126. package/dist/cli/error-handler.js +65 -0
  127. package/dist/cli/error-handler.js.map +1 -0
  128. package/dist/cli/index.d.ts +48 -0
  129. package/dist/cli/index.d.ts.map +1 -0
  130. package/dist/cli/index.js +99 -0
  131. package/dist/cli/index.js.map +1 -0
  132. package/dist/cli/output.d.ts +94 -0
  133. package/dist/cli/output.d.ts.map +1 -0
  134. package/dist/cli/output.js +124 -0
  135. package/dist/cli/output.js.map +1 -0
  136. package/dist/cli/prompt.d.ts +48 -0
  137. package/dist/cli/prompt.d.ts.map +1 -0
  138. package/dist/cli/prompt.js +96 -0
  139. package/dist/cli/prompt.js.map +1 -0
  140. package/dist/clients/cache.d.ts +63 -0
  141. package/dist/clients/cache.d.ts.map +1 -0
  142. package/dist/clients/cache.js +160 -0
  143. package/dist/clients/cache.js.map +1 -0
  144. package/dist/clients/crypto.d.ts +69 -0
  145. package/dist/clients/crypto.d.ts.map +1 -0
  146. package/dist/clients/crypto.js +83 -0
  147. package/dist/clients/crypto.js.map +1 -0
  148. package/dist/clients/errors.d.ts +27 -0
  149. package/dist/clients/errors.d.ts.map +1 -0
  150. package/dist/clients/errors.js +33 -0
  151. package/dist/clients/errors.js.map +1 -0
  152. package/dist/clients/index.d.ts +19 -0
  153. package/dist/clients/index.d.ts.map +1 -0
  154. package/dist/clients/index.js +23 -0
  155. package/dist/clients/index.js.map +1 -0
  156. package/dist/clients/repository.d.ts +161 -0
  157. package/dist/clients/repository.d.ts.map +1 -0
  158. package/dist/clients/repository.js +318 -0
  159. package/dist/clients/repository.js.map +1 -0
  160. package/dist/clients/resolve-login-methods.d.ts +74 -0
  161. package/dist/clients/resolve-login-methods.d.ts.map +1 -0
  162. package/dist/clients/resolve-login-methods.js +68 -0
  163. package/dist/clients/resolve-login-methods.js.map +1 -0
  164. package/dist/clients/secret-repository.d.ts +109 -0
  165. package/dist/clients/secret-repository.d.ts.map +1 -0
  166. package/dist/clients/secret-repository.js +166 -0
  167. package/dist/clients/secret-repository.js.map +1 -0
  168. package/dist/clients/secret-service.d.ts +87 -0
  169. package/dist/clients/secret-service.d.ts.map +1 -0
  170. package/dist/clients/secret-service.js +204 -0
  171. package/dist/clients/secret-service.js.map +1 -0
  172. package/dist/clients/service.d.ts +158 -0
  173. package/dist/clients/service.d.ts.map +1 -0
  174. package/dist/clients/service.js +523 -0
  175. package/dist/clients/service.js.map +1 -0
  176. package/dist/clients/types.d.ts +214 -0
  177. package/dist/clients/types.d.ts.map +1 -0
  178. package/dist/clients/types.js +77 -0
  179. package/dist/clients/types.js.map +1 -0
  180. package/dist/clients/validators.d.ts +87 -0
  181. package/dist/clients/validators.d.ts.map +1 -0
  182. package/dist/clients/validators.js +164 -0
  183. package/dist/clients/validators.js.map +1 -0
  184. package/dist/config/index.d.ts +23 -0
  185. package/dist/config/index.d.ts.map +1 -0
  186. package/dist/config/index.js +52 -0
  187. package/dist/config/index.js.map +1 -0
  188. package/dist/config/schema.d.ts +35 -0
  189. package/dist/config/schema.d.ts.map +1 -0
  190. package/dist/config/schema.js +167 -0
  191. package/dist/config/schema.js.map +1 -0
  192. package/dist/custom-claims/cache.d.ts +48 -0
  193. package/dist/custom-claims/cache.d.ts.map +1 -0
  194. package/dist/custom-claims/cache.js +122 -0
  195. package/dist/custom-claims/cache.js.map +1 -0
  196. package/dist/custom-claims/errors.d.ts +25 -0
  197. package/dist/custom-claims/errors.d.ts.map +1 -0
  198. package/dist/custom-claims/errors.js +31 -0
  199. package/dist/custom-claims/errors.js.map +1 -0
  200. package/dist/custom-claims/index.d.ts +14 -0
  201. package/dist/custom-claims/index.d.ts.map +1 -0
  202. package/dist/custom-claims/index.js +17 -0
  203. package/dist/custom-claims/index.js.map +1 -0
  204. package/dist/custom-claims/repository.d.ts +147 -0
  205. package/dist/custom-claims/repository.d.ts.map +1 -0
  206. package/dist/custom-claims/repository.js +338 -0
  207. package/dist/custom-claims/repository.js.map +1 -0
  208. package/dist/custom-claims/service.d.ts +129 -0
  209. package/dist/custom-claims/service.d.ts.map +1 -0
  210. package/dist/custom-claims/service.js +296 -0
  211. package/dist/custom-claims/service.js.map +1 -0
  212. package/dist/custom-claims/types.d.ts +132 -0
  213. package/dist/custom-claims/types.d.ts.map +1 -0
  214. package/dist/custom-claims/types.js +61 -0
  215. package/dist/custom-claims/types.js.map +1 -0
  216. package/dist/custom-claims/validators.d.ts +61 -0
  217. package/dist/custom-claims/validators.d.ts.map +1 -0
  218. package/dist/custom-claims/validators.js +136 -0
  219. package/dist/custom-claims/validators.js.map +1 -0
  220. package/dist/index.d.ts +14 -0
  221. package/dist/index.d.ts.map +1 -0
  222. package/dist/index.js +91 -0
  223. package/dist/index.js.map +1 -0
  224. package/dist/lib/admin-permissions.d.ts +147 -0
  225. package/dist/lib/admin-permissions.d.ts.map +1 -0
  226. package/dist/lib/admin-permissions.js +261 -0
  227. package/dist/lib/admin-permissions.js.map +1 -0
  228. package/dist/lib/audit-log.d.ts +45 -0
  229. package/dist/lib/audit-log.d.ts.map +1 -0
  230. package/dist/lib/audit-log.js +79 -0
  231. package/dist/lib/audit-log.js.map +1 -0
  232. package/dist/lib/branding-assets.d.ts +47 -0
  233. package/dist/lib/branding-assets.d.ts.map +1 -0
  234. package/dist/lib/branding-assets.js +93 -0
  235. package/dist/lib/branding-assets.js.map +1 -0
  236. package/dist/lib/bulk-operations.d.ts +54 -0
  237. package/dist/lib/bulk-operations.d.ts.map +1 -0
  238. package/dist/lib/bulk-operations.js +201 -0
  239. package/dist/lib/bulk-operations.js.map +1 -0
  240. package/dist/lib/cursor.d.ts +110 -0
  241. package/dist/lib/cursor.d.ts.map +1 -0
  242. package/dist/lib/cursor.js +115 -0
  243. package/dist/lib/cursor.js.map +1 -0
  244. package/dist/lib/data-export.d.ts +67 -0
  245. package/dist/lib/data-export.d.ts.map +1 -0
  246. package/dist/lib/data-export.js +272 -0
  247. package/dist/lib/data-export.js.map +1 -0
  248. package/dist/lib/data-import-plan.d.ts +50 -0
  249. package/dist/lib/data-import-plan.d.ts.map +1 -0
  250. package/dist/lib/data-import-plan.js +235 -0
  251. package/dist/lib/data-import-plan.js.map +1 -0
  252. package/dist/lib/data-import.d.ts +276 -0
  253. package/dist/lib/data-import.d.ts.map +1 -0
  254. package/dist/lib/data-import.js +1694 -0
  255. package/dist/lib/data-import.js.map +1 -0
  256. package/dist/lib/database.d.ts +22 -0
  257. package/dist/lib/database.d.ts.map +1 -0
  258. package/dist/lib/database.js +103 -0
  259. package/dist/lib/database.js.map +1 -0
  260. package/dist/lib/entity-history.d.ts +52 -0
  261. package/dist/lib/entity-history.d.ts.map +1 -0
  262. package/dist/lib/entity-history.js +121 -0
  263. package/dist/lib/entity-history.js.map +1 -0
  264. package/dist/lib/etag.d.ts +92 -0
  265. package/dist/lib/etag.d.ts.map +1 -0
  266. package/dist/lib/etag.js +155 -0
  267. package/dist/lib/etag.js.map +1 -0
  268. package/dist/lib/image-validator.d.ts +44 -0
  269. package/dist/lib/image-validator.d.ts.map +1 -0
  270. package/dist/lib/image-validator.js +204 -0
  271. package/dist/lib/image-validator.js.map +1 -0
  272. package/dist/lib/logger.d.ts +15 -0
  273. package/dist/lib/logger.d.ts.map +1 -0
  274. package/dist/lib/logger.js +84 -0
  275. package/dist/lib/logger.js.map +1 -0
  276. package/dist/lib/migrator.d.ts +14 -0
  277. package/dist/lib/migrator.d.ts.map +1 -0
  278. package/dist/lib/migrator.js +34 -0
  279. package/dist/lib/migrator.js.map +1 -0
  280. package/dist/lib/redis.d.ts +5 -0
  281. package/dist/lib/redis.d.ts.map +1 -0
  282. package/dist/lib/redis.js +29 -0
  283. package/dist/lib/redis.js.map +1 -0
  284. package/dist/lib/runtime-paths.d.ts +38 -0
  285. package/dist/lib/runtime-paths.d.ts.map +1 -0
  286. package/dist/lib/runtime-paths.js +50 -0
  287. package/dist/lib/runtime-paths.js.map +1 -0
  288. package/dist/lib/session-tracking.d.ts +81 -0
  289. package/dist/lib/session-tracking.d.ts.map +1 -0
  290. package/dist/lib/session-tracking.js +145 -0
  291. package/dist/lib/session-tracking.js.map +1 -0
  292. package/dist/lib/signing-key-crypto.d.ts +53 -0
  293. package/dist/lib/signing-key-crypto.d.ts.map +1 -0
  294. package/dist/lib/signing-key-crypto.js +108 -0
  295. package/dist/lib/signing-key-crypto.js.map +1 -0
  296. package/dist/lib/signing-keys.d.ts +141 -0
  297. package/dist/lib/signing-keys.d.ts.map +1 -0
  298. package/dist/lib/signing-keys.js +206 -0
  299. package/dist/lib/signing-keys.js.map +1 -0
  300. package/dist/lib/stats.d.ts +83 -0
  301. package/dist/lib/stats.d.ts.map +1 -0
  302. package/dist/lib/stats.js +187 -0
  303. package/dist/lib/stats.js.map +1 -0
  304. package/dist/lib/super-admin-protection.d.ts +69 -0
  305. package/dist/lib/super-admin-protection.d.ts.map +1 -0
  306. package/dist/lib/super-admin-protection.js +102 -0
  307. package/dist/lib/super-admin-protection.js.map +1 -0
  308. package/dist/lib/system-config.d.ts +79 -0
  309. package/dist/lib/system-config.d.ts.map +1 -0
  310. package/dist/lib/system-config.js +159 -0
  311. package/dist/lib/system-config.js.map +1 -0
  312. package/dist/middleware/admin-auth.d.ts +100 -0
  313. package/dist/middleware/admin-auth.d.ts.map +1 -0
  314. package/dist/middleware/admin-auth.js +241 -0
  315. package/dist/middleware/admin-auth.js.map +1 -0
  316. package/dist/middleware/admin-cors.d.ts +41 -0
  317. package/dist/middleware/admin-cors.d.ts.map +1 -0
  318. package/dist/middleware/admin-cors.js +83 -0
  319. package/dist/middleware/admin-cors.js.map +1 -0
  320. package/dist/middleware/admin-mutation-audit.d.ts +9 -0
  321. package/dist/middleware/admin-mutation-audit.d.ts.map +1 -0
  322. package/dist/middleware/admin-mutation-audit.js +76 -0
  323. package/dist/middleware/admin-mutation-audit.js.map +1 -0
  324. package/dist/middleware/admin-rate-limiter.d.ts +56 -0
  325. package/dist/middleware/admin-rate-limiter.d.ts.map +1 -0
  326. package/dist/middleware/admin-rate-limiter.js +97 -0
  327. package/dist/middleware/admin-rate-limiter.js.map +1 -0
  328. package/dist/middleware/client-secret-hash.d.ts +34 -0
  329. package/dist/middleware/client-secret-hash.d.ts.map +1 -0
  330. package/dist/middleware/client-secret-hash.js +74 -0
  331. package/dist/middleware/client-secret-hash.js.map +1 -0
  332. package/dist/middleware/error-handler.d.ts +3 -0
  333. package/dist/middleware/error-handler.d.ts.map +1 -0
  334. package/dist/middleware/error-handler.js +93 -0
  335. package/dist/middleware/error-handler.js.map +1 -0
  336. package/dist/middleware/health.d.ts +3 -0
  337. package/dist/middleware/health.d.ts.map +1 -0
  338. package/dist/middleware/health.js +35 -0
  339. package/dist/middleware/health.js.map +1 -0
  340. package/dist/middleware/metrics.d.ts +40 -0
  341. package/dist/middleware/metrics.d.ts.map +1 -0
  342. package/dist/middleware/metrics.js +75 -0
  343. package/dist/middleware/metrics.js.map +1 -0
  344. package/dist/middleware/oidc-client-tenant.d.ts +37 -0
  345. package/dist/middleware/oidc-client-tenant.d.ts.map +1 -0
  346. package/dist/middleware/oidc-client-tenant.js +156 -0
  347. package/dist/middleware/oidc-client-tenant.js.map +1 -0
  348. package/dist/middleware/oidc-cors.d.ts +33 -0
  349. package/dist/middleware/oidc-cors.d.ts.map +1 -0
  350. package/dist/middleware/oidc-cors.js +68 -0
  351. package/dist/middleware/oidc-cors.js.map +1 -0
  352. package/dist/middleware/oidc-preflight-cors.d.ts +54 -0
  353. package/dist/middleware/oidc-preflight-cors.d.ts.map +1 -0
  354. package/dist/middleware/oidc-preflight-cors.js +267 -0
  355. package/dist/middleware/oidc-preflight-cors.js.map +1 -0
  356. package/dist/middleware/prompt-login-reset.d.ts +103 -0
  357. package/dist/middleware/prompt-login-reset.d.ts.map +1 -0
  358. package/dist/middleware/prompt-login-reset.js +204 -0
  359. package/dist/middleware/prompt-login-reset.js.map +1 -0
  360. package/dist/middleware/ready.d.ts +23 -0
  361. package/dist/middleware/ready.d.ts.map +1 -0
  362. package/dist/middleware/ready.js +60 -0
  363. package/dist/middleware/ready.js.map +1 -0
  364. package/dist/middleware/request-logger.d.ts +27 -0
  365. package/dist/middleware/request-logger.d.ts.map +1 -0
  366. package/dist/middleware/request-logger.js +46 -0
  367. package/dist/middleware/request-logger.js.map +1 -0
  368. package/dist/middleware/require-permission.d.ts +28 -0
  369. package/dist/middleware/require-permission.d.ts.map +1 -0
  370. package/dist/middleware/require-permission.js +63 -0
  371. package/dist/middleware/require-permission.js.map +1 -0
  372. package/dist/middleware/require-user-organization.d.ts +18 -0
  373. package/dist/middleware/require-user-organization.d.ts.map +1 -0
  374. package/dist/middleware/require-user-organization.js +53 -0
  375. package/dist/middleware/require-user-organization.js.map +1 -0
  376. package/dist/middleware/root-page.d.ts +62 -0
  377. package/dist/middleware/root-page.d.ts.map +1 -0
  378. package/dist/middleware/root-page.js +134 -0
  379. package/dist/middleware/root-page.js.map +1 -0
  380. package/dist/middleware/security-headers.d.ts +98 -0
  381. package/dist/middleware/security-headers.d.ts.map +1 -0
  382. package/dist/middleware/security-headers.js +159 -0
  383. package/dist/middleware/security-headers.js.map +1 -0
  384. package/dist/middleware/tenant-resolver.d.ts +37 -0
  385. package/dist/middleware/tenant-resolver.d.ts.map +1 -0
  386. package/dist/middleware/tenant-resolver.js +71 -0
  387. package/dist/middleware/tenant-resolver.js.map +1 -0
  388. package/dist/middleware/token-rate-limiter.d.ts +89 -0
  389. package/dist/middleware/token-rate-limiter.d.ts.map +1 -0
  390. package/dist/middleware/token-rate-limiter.js +189 -0
  391. package/dist/middleware/token-rate-limiter.js.map +1 -0
  392. package/dist/oidc/account-finder.d.ts +52 -0
  393. package/dist/oidc/account-finder.d.ts.map +1 -0
  394. package/dist/oidc/account-finder.js +134 -0
  395. package/dist/oidc/account-finder.js.map +1 -0
  396. package/dist/oidc/adapter-factory.d.ts +90 -0
  397. package/dist/oidc/adapter-factory.d.ts.map +1 -0
  398. package/dist/oidc/adapter-factory.js +165 -0
  399. package/dist/oidc/adapter-factory.js.map +1 -0
  400. package/dist/oidc/configuration.d.ts +155 -0
  401. package/dist/oidc/configuration.d.ts.map +1 -0
  402. package/dist/oidc/configuration.js +531 -0
  403. package/dist/oidc/configuration.js.map +1 -0
  404. package/dist/oidc/postgres-adapter.d.ts +159 -0
  405. package/dist/oidc/postgres-adapter.d.ts.map +1 -0
  406. package/dist/oidc/postgres-adapter.js +222 -0
  407. package/dist/oidc/postgres-adapter.js.map +1 -0
  408. package/dist/oidc/protocol-security-observer.d.ts +38 -0
  409. package/dist/oidc/protocol-security-observer.d.ts.map +1 -0
  410. package/dist/oidc/protocol-security-observer.js +93 -0
  411. package/dist/oidc/protocol-security-observer.js.map +1 -0
  412. package/dist/oidc/provider.d.ts +37 -0
  413. package/dist/oidc/provider.d.ts.map +1 -0
  414. package/dist/oidc/provider.js +71 -0
  415. package/dist/oidc/provider.js.map +1 -0
  416. package/dist/oidc/redis-adapter.d.ts +140 -0
  417. package/dist/oidc/redis-adapter.d.ts.map +1 -0
  418. package/dist/oidc/redis-adapter.js +344 -0
  419. package/dist/oidc/redis-adapter.js.map +1 -0
  420. package/dist/organizations/cache.d.ts +60 -0
  421. package/dist/organizations/cache.d.ts.map +1 -0
  422. package/dist/organizations/cache.js +157 -0
  423. package/dist/organizations/cache.js.map +1 -0
  424. package/dist/organizations/errors.d.ts +25 -0
  425. package/dist/organizations/errors.d.ts.map +1 -0
  426. package/dist/organizations/errors.js +31 -0
  427. package/dist/organizations/errors.js.map +1 -0
  428. package/dist/organizations/index.d.ts +15 -0
  429. package/dist/organizations/index.d.ts.map +1 -0
  430. package/dist/organizations/index.js +15 -0
  431. package/dist/organizations/index.js.map +1 -0
  432. package/dist/organizations/repository.d.ts +183 -0
  433. package/dist/organizations/repository.d.ts.map +1 -0
  434. package/dist/organizations/repository.js +354 -0
  435. package/dist/organizations/repository.js.map +1 -0
  436. package/dist/organizations/service.d.ts +168 -0
  437. package/dist/organizations/service.d.ts.map +1 -0
  438. package/dist/organizations/service.js +511 -0
  439. package/dist/organizations/service.js.map +1 -0
  440. package/dist/organizations/slugs.d.ts +57 -0
  441. package/dist/organizations/slugs.d.ts.map +1 -0
  442. package/dist/organizations/slugs.js +130 -0
  443. package/dist/organizations/slugs.js.map +1 -0
  444. package/dist/organizations/types.d.ts +146 -0
  445. package/dist/organizations/types.d.ts.map +1 -0
  446. package/dist/organizations/types.js +49 -0
  447. package/dist/organizations/types.js.map +1 -0
  448. package/dist/rbac/cache.d.ts +110 -0
  449. package/dist/rbac/cache.d.ts.map +1 -0
  450. package/dist/rbac/cache.js +271 -0
  451. package/dist/rbac/cache.js.map +1 -0
  452. package/dist/rbac/errors.d.ts +34 -0
  453. package/dist/rbac/errors.d.ts.map +1 -0
  454. package/dist/rbac/errors.js +43 -0
  455. package/dist/rbac/errors.js.map +1 -0
  456. package/dist/rbac/index.d.ts +17 -0
  457. package/dist/rbac/index.d.ts.map +1 -0
  458. package/dist/rbac/index.js +21 -0
  459. package/dist/rbac/index.js.map +1 -0
  460. package/dist/rbac/mapping-repository.d.ts +121 -0
  461. package/dist/rbac/mapping-repository.d.ts.map +1 -0
  462. package/dist/rbac/mapping-repository.js +224 -0
  463. package/dist/rbac/mapping-repository.js.map +1 -0
  464. package/dist/rbac/permission-repository.d.ts +100 -0
  465. package/dist/rbac/permission-repository.d.ts.map +1 -0
  466. package/dist/rbac/permission-repository.js +190 -0
  467. package/dist/rbac/permission-repository.js.map +1 -0
  468. package/dist/rbac/permission-service.d.ts +85 -0
  469. package/dist/rbac/permission-service.d.ts.map +1 -0
  470. package/dist/rbac/permission-service.js +179 -0
  471. package/dist/rbac/permission-service.js.map +1 -0
  472. package/dist/rbac/role-repository.d.ts +104 -0
  473. package/dist/rbac/role-repository.d.ts.map +1 -0
  474. package/dist/rbac/role-repository.js +202 -0
  475. package/dist/rbac/role-repository.js.map +1 -0
  476. package/dist/rbac/role-service.d.ts +111 -0
  477. package/dist/rbac/role-service.d.ts.map +1 -0
  478. package/dist/rbac/role-service.js +256 -0
  479. package/dist/rbac/role-service.js.map +1 -0
  480. package/dist/rbac/slugs.d.ts +116 -0
  481. package/dist/rbac/slugs.d.ts.map +1 -0
  482. package/dist/rbac/slugs.js +178 -0
  483. package/dist/rbac/slugs.js.map +1 -0
  484. package/dist/rbac/types.d.ts +187 -0
  485. package/dist/rbac/types.d.ts.map +1 -0
  486. package/dist/rbac/types.js +75 -0
  487. package/dist/rbac/types.js.map +1 -0
  488. package/dist/rbac/user-role-service.d.ts +101 -0
  489. package/dist/rbac/user-role-service.d.ts.map +1 -0
  490. package/dist/rbac/user-role-service.js +166 -0
  491. package/dist/rbac/user-role-service.js.map +1 -0
  492. package/dist/routes/applications.d.ts +40 -0
  493. package/dist/routes/applications.d.ts.map +1 -0
  494. package/dist/routes/applications.js +284 -0
  495. package/dist/routes/applications.js.map +1 -0
  496. package/dist/routes/audit.d.ts +31 -0
  497. package/dist/routes/audit.d.ts.map +1 -0
  498. package/dist/routes/audit.js +140 -0
  499. package/dist/routes/audit.js.map +1 -0
  500. package/dist/routes/branding.d.ts +17 -0
  501. package/dist/routes/branding.d.ts.map +1 -0
  502. package/dist/routes/branding.js +104 -0
  503. package/dist/routes/branding.js.map +1 -0
  504. package/dist/routes/bulk.d.ts +37 -0
  505. package/dist/routes/bulk.d.ts.map +1 -0
  506. package/dist/routes/bulk.js +94 -0
  507. package/dist/routes/bulk.js.map +1 -0
  508. package/dist/routes/clients.d.ts +44 -0
  509. package/dist/routes/clients.d.ts.map +1 -0
  510. package/dist/routes/clients.js +353 -0
  511. package/dist/routes/clients.js.map +1 -0
  512. package/dist/routes/config.d.ts +35 -0
  513. package/dist/routes/config.d.ts.map +1 -0
  514. package/dist/routes/config.js +115 -0
  515. package/dist/routes/config.js.map +1 -0
  516. package/dist/routes/custom-claims.d.ts +38 -0
  517. package/dist/routes/custom-claims.d.ts.map +1 -0
  518. package/dist/routes/custom-claims.js +208 -0
  519. package/dist/routes/custom-claims.js.map +1 -0
  520. package/dist/routes/exports.d.ts +21 -0
  521. package/dist/routes/exports.d.ts.map +1 -0
  522. package/dist/routes/exports.js +98 -0
  523. package/dist/routes/exports.js.map +1 -0
  524. package/dist/routes/imports.d.ts +18 -0
  525. package/dist/routes/imports.d.ts.map +1 -0
  526. package/dist/routes/imports.js +72 -0
  527. package/dist/routes/imports.js.map +1 -0
  528. package/dist/routes/interactions.d.ts +111 -0
  529. package/dist/routes/interactions.d.ts.map +1 -0
  530. package/dist/routes/interactions.js +1074 -0
  531. package/dist/routes/interactions.js.map +1 -0
  532. package/dist/routes/invitation.d.ts +31 -0
  533. package/dist/routes/invitation.d.ts.map +1 -0
  534. package/dist/routes/invitation.js +342 -0
  535. package/dist/routes/invitation.js.map +1 -0
  536. package/dist/routes/keys.d.ts +28 -0
  537. package/dist/routes/keys.d.ts.map +1 -0
  538. package/dist/routes/keys.js +91 -0
  539. package/dist/routes/keys.js.map +1 -0
  540. package/dist/routes/magic-link.d.ts +43 -0
  541. package/dist/routes/magic-link.d.ts.map +1 -0
  542. package/dist/routes/magic-link.js +264 -0
  543. package/dist/routes/magic-link.js.map +1 -0
  544. package/dist/routes/organizations.d.ts +38 -0
  545. package/dist/routes/organizations.d.ts.map +1 -0
  546. package/dist/routes/organizations.js +347 -0
  547. package/dist/routes/organizations.js.map +1 -0
  548. package/dist/routes/password-reset.d.ts +65 -0
  549. package/dist/routes/password-reset.d.ts.map +1 -0
  550. package/dist/routes/password-reset.js +493 -0
  551. package/dist/routes/password-reset.js.map +1 -0
  552. package/dist/routes/permissions.d.ts +33 -0
  553. package/dist/routes/permissions.d.ts.map +1 -0
  554. package/dist/routes/permissions.js +166 -0
  555. package/dist/routes/permissions.js.map +1 -0
  556. package/dist/routes/roles.d.ts +37 -0
  557. package/dist/routes/roles.d.ts.map +1 -0
  558. package/dist/routes/roles.js +222 -0
  559. package/dist/routes/roles.js.map +1 -0
  560. package/dist/routes/sessions.d.ts +37 -0
  561. package/dist/routes/sessions.d.ts.map +1 -0
  562. package/dist/routes/sessions.js +121 -0
  563. package/dist/routes/sessions.js.map +1 -0
  564. package/dist/routes/stats.d.ts +28 -0
  565. package/dist/routes/stats.d.ts.map +1 -0
  566. package/dist/routes/stats.js +65 -0
  567. package/dist/routes/stats.js.map +1 -0
  568. package/dist/routes/two-factor-admin.d.ts +54 -0
  569. package/dist/routes/two-factor-admin.d.ts.map +1 -0
  570. package/dist/routes/two-factor-admin.js +344 -0
  571. package/dist/routes/two-factor-admin.js.map +1 -0
  572. package/dist/routes/two-factor.d.ts +31 -0
  573. package/dist/routes/two-factor.d.ts.map +1 -0
  574. package/dist/routes/two-factor.js +595 -0
  575. package/dist/routes/two-factor.js.map +1 -0
  576. package/dist/routes/user-roles.d.ts +33 -0
  577. package/dist/routes/user-roles.d.ts.map +1 -0
  578. package/dist/routes/user-roles.js +129 -0
  579. package/dist/routes/user-roles.js.map +1 -0
  580. package/dist/routes/users.d.ts +61 -0
  581. package/dist/routes/users.d.ts.map +1 -0
  582. package/dist/routes/users.js +868 -0
  583. package/dist/routes/users.js.map +1 -0
  584. package/dist/security/decision-context.d.ts +52 -0
  585. package/dist/security/decision-context.d.ts.map +1 -0
  586. package/dist/security/decision-context.js +150 -0
  587. package/dist/security/decision-context.js.map +1 -0
  588. package/dist/security/decision-event.d.ts +128 -0
  589. package/dist/security/decision-event.d.ts.map +1 -0
  590. package/dist/security/decision-event.js +225 -0
  591. package/dist/security/decision-event.js.map +1 -0
  592. package/dist/security/transport-decision.d.ts +6 -0
  593. package/dist/security/transport-decision.d.ts.map +1 -0
  594. package/dist/security/transport-decision.js +37 -0
  595. package/dist/security/transport-decision.js.map +1 -0
  596. package/dist/server.d.ts +50 -0
  597. package/dist/server.d.ts.map +1 -0
  598. package/dist/server.js +491 -0
  599. package/dist/server.js.map +1 -0
  600. package/dist/two-factor/cache.d.ts +47 -0
  601. package/dist/two-factor/cache.d.ts.map +1 -0
  602. package/dist/two-factor/cache.js +122 -0
  603. package/dist/two-factor/cache.js.map +1 -0
  604. package/dist/two-factor/crypto.d.ts +41 -0
  605. package/dist/two-factor/crypto.d.ts.map +1 -0
  606. package/dist/two-factor/crypto.js +94 -0
  607. package/dist/two-factor/crypto.js.map +1 -0
  608. package/dist/two-factor/errors.d.ts +82 -0
  609. package/dist/two-factor/errors.d.ts.map +1 -0
  610. package/dist/two-factor/errors.js +112 -0
  611. package/dist/two-factor/errors.js.map +1 -0
  612. package/dist/two-factor/index.d.ts +18 -0
  613. package/dist/two-factor/index.d.ts.map +1 -0
  614. package/dist/two-factor/index.js +25 -0
  615. package/dist/two-factor/index.js.map +1 -0
  616. package/dist/two-factor/otp.d.ts +43 -0
  617. package/dist/two-factor/otp.d.ts.map +1 -0
  618. package/dist/two-factor/otp.js +57 -0
  619. package/dist/two-factor/otp.js.map +1 -0
  620. package/dist/two-factor/recovery.d.ts +45 -0
  621. package/dist/two-factor/recovery.d.ts.map +1 -0
  622. package/dist/two-factor/recovery.js +104 -0
  623. package/dist/two-factor/recovery.js.map +1 -0
  624. package/dist/two-factor/repository.d.ts +156 -0
  625. package/dist/two-factor/repository.d.ts.map +1 -0
  626. package/dist/two-factor/repository.js +251 -0
  627. package/dist/two-factor/repository.js.map +1 -0
  628. package/dist/two-factor/service.d.ts +232 -0
  629. package/dist/two-factor/service.d.ts.map +1 -0
  630. package/dist/two-factor/service.js +599 -0
  631. package/dist/two-factor/service.js.map +1 -0
  632. package/dist/two-factor/totp.d.ts +57 -0
  633. package/dist/two-factor/totp.d.ts.map +1 -0
  634. package/dist/two-factor/totp.js +96 -0
  635. package/dist/two-factor/totp.js.map +1 -0
  636. package/dist/two-factor/types.d.ts +152 -0
  637. package/dist/two-factor/types.d.ts.map +1 -0
  638. package/dist/two-factor/types.js +64 -0
  639. package/dist/two-factor/types.js.map +1 -0
  640. package/dist/users/cache.d.ts +49 -0
  641. package/dist/users/cache.d.ts.map +1 -0
  642. package/dist/users/cache.js +140 -0
  643. package/dist/users/cache.js.map +1 -0
  644. package/dist/users/claims.d.ts +67 -0
  645. package/dist/users/claims.d.ts.map +1 -0
  646. package/dist/users/claims.js +104 -0
  647. package/dist/users/claims.js.map +1 -0
  648. package/dist/users/errors.d.ts +25 -0
  649. package/dist/users/errors.d.ts.map +1 -0
  650. package/dist/users/errors.js +31 -0
  651. package/dist/users/errors.js.map +1 -0
  652. package/dist/users/gdpr.d.ts +110 -0
  653. package/dist/users/gdpr.d.ts.map +1 -0
  654. package/dist/users/gdpr.js +211 -0
  655. package/dist/users/gdpr.js.map +1 -0
  656. package/dist/users/index.d.ts +20 -0
  657. package/dist/users/index.d.ts.map +1 -0
  658. package/dist/users/index.js +19 -0
  659. package/dist/users/index.js.map +1 -0
  660. package/dist/users/password.d.ts +85 -0
  661. package/dist/users/password.d.ts.map +1 -0
  662. package/dist/users/password.js +138 -0
  663. package/dist/users/password.js.map +1 -0
  664. package/dist/users/repository.d.ts +263 -0
  665. package/dist/users/repository.d.ts.map +1 -0
  666. package/dist/users/repository.js +499 -0
  667. package/dist/users/repository.js.map +1 -0
  668. package/dist/users/service.d.ts +299 -0
  669. package/dist/users/service.d.ts.map +1 -0
  670. package/dist/users/service.js +698 -0
  671. package/dist/users/service.js.map +1 -0
  672. package/dist/users/types.d.ts +220 -0
  673. package/dist/users/types.d.ts.map +1 -0
  674. package/dist/users/types.js +77 -0
  675. package/dist/users/types.js.map +1 -0
  676. package/locales/default/en/common.json +10 -0
  677. package/locales/default/en/consent.json +13 -0
  678. package/locales/default/en/emails.json +17 -0
  679. package/locales/default/en/errors.json +21 -0
  680. package/locales/default/en/forgot-password.json +11 -0
  681. package/locales/default/en/invitation.json +18 -0
  682. package/locales/default/en/login.json +17 -0
  683. package/locales/default/en/logout.json +9 -0
  684. package/locales/default/en/magic-link.json +12 -0
  685. package/locales/default/en/reset-password.json +16 -0
  686. package/locales/default/en/two-factor.json +29 -0
  687. package/migrations/.gitkeep +0 -0
  688. package/migrations/001_extensions.sql +22 -0
  689. package/migrations/002_organizations.sql +43 -0
  690. package/migrations/003_applications.sql +50 -0
  691. package/migrations/004_clients.sql +74 -0
  692. package/migrations/005_users.sql +119 -0
  693. package/migrations/006_roles_permissions.sql +80 -0
  694. package/migrations/007_custom_claims.sql +55 -0
  695. package/migrations/008_config.sql +51 -0
  696. package/migrations/009_audit_log.sql +31 -0
  697. package/migrations/010_oidc_adapter.sql +34 -0
  698. package/migrations/011_seed.sql +53 -0
  699. package/migrations/012_two_factor.sql +88 -0
  700. package/migrations/013_client_secret_sha256.sql +22 -0
  701. package/migrations/014_login_methods.sql +34 -0
  702. package/migrations/015_signing_key_encryption.sql +20 -0
  703. package/migrations/016_failed_login_count.sql +27 -0
  704. package/migrations/017_audit_retention.sql +11 -0
  705. package/migrations/018_admin_api_enhancements.sql +78 -0
  706. package/migrations/019_invitation_details.sql +27 -0
  707. package/migrations/020_two_factor_admin_permission.sql +108 -0
  708. package/migrations/021_auth_recovery_jobs.sql +74 -0
  709. package/migrations/022_recovery_artifact_ownership.sql +25 -0
  710. package/migrations/023_magic_link_authority.sql +39 -0
  711. package/package.json +106 -0
  712. package/templates/default/emails/invitation.hbs +39 -0
  713. package/templates/default/emails/invitation.txt.hbs +18 -0
  714. package/templates/default/emails/magic-link.hbs +30 -0
  715. package/templates/default/emails/magic-link.txt.hbs +11 -0
  716. package/templates/default/emails/otp-code.hbs +31 -0
  717. package/templates/default/emails/otp-code.txt.hbs +15 -0
  718. package/templates/default/emails/password-changed.hbs +24 -0
  719. package/templates/default/emails/password-changed.txt.hbs +7 -0
  720. package/templates/default/emails/password-reset.hbs +30 -0
  721. package/templates/default/emails/password-reset.txt.hbs +11 -0
  722. package/templates/default/emails/welcome.hbs +25 -0
  723. package/templates/default/emails/welcome.txt.hbs +9 -0
  724. package/templates/default/layouts/main.hbs +49 -0
  725. package/templates/default/pages/accept-invite.hbs +25 -0
  726. package/templates/default/pages/consent.hbs +27 -0
  727. package/templates/default/pages/error.hbs +15 -0
  728. package/templates/default/pages/forgot-password.hbs +21 -0
  729. package/templates/default/pages/invite-expired.hbs +6 -0
  730. package/templates/default/pages/invite-success.hbs +9 -0
  731. package/templates/default/pages/login.hbs +108 -0
  732. package/templates/default/pages/logout-success.hbs +5 -0
  733. package/templates/default/pages/logout.hbs +24 -0
  734. package/templates/default/pages/magic-link-sent.hbs +10 -0
  735. package/templates/default/pages/magic-link-success.hbs +17 -0
  736. package/templates/default/pages/reset-password.hbs +20 -0
  737. package/templates/default/pages/reset-success.hbs +9 -0
  738. package/templates/default/pages/two-factor-setup.hbs +65 -0
  739. package/templates/default/pages/two-factor-verify.hbs +77 -0
  740. package/templates/default/partials/flash-messages.hbs +10 -0
  741. package/templates/default/partials/footer.hbs +4 -0
  742. package/templates/default/partials/header.hbs +8 -0
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Global HTTP security headers middleware.
3
+ *
4
+ * Adds defence-in-depth security headers to every response produced by
5
+ * the Porta application. The headers mitigate a broad class of browser-
6
+ * side attacks (clickjacking, MIME-sniffing, cross-origin information
7
+ * leakage, protocol downgrade) without depending on an upstream reverse
8
+ * proxy — if the proxy is a dumb passthrough, these headers still reach
9
+ * the browser.
10
+ *
11
+ * Headers set on every response:
12
+ * X-Content-Type-Options: nosniff — prevent MIME-sniffing
13
+ * X-Frame-Options: DENY — prevent clickjacking
14
+ * Referrer-Policy: strict-origin-when-cross-origin
15
+ * — limit referrer leakage
16
+ * X-XSS-Protection: 0 — disable legacy XSS filter
17
+ * (buggy; rely on CSP instead)
18
+ * Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
19
+ * — restrict browser APIs
20
+ * Content-Security-Policy — strict default, relaxed for
21
+ * HTML pages (see below)
22
+ *
23
+ * Conditional headers:
24
+ * Strict-Transport-Security — only emitted when the
25
+ * configured issuer URL uses https://
26
+ *
27
+ * Content-Security-Policy strategy:
28
+ * - Default (JSON / non-HTML responses):
29
+ * `default-src 'none'` — nothing to render, nothing to load.
30
+ * - HTML responses (login, consent, 2FA, password-reset, etc.):
31
+ * `default-src 'none'; style-src 'unsafe-inline'; frame-ancestors 'none'`
32
+ * The interaction templates use inline `<style>` blocks and may
33
+ * inject custom branding CSS via `{{{branding.customCss}}}`, hence
34
+ * `style-src 'unsafe-inline'` is required. Login pages must never
35
+ * be embedded in iframes (`frame-ancestors 'none'`).
36
+ *
37
+ * Note: `form-action` is intentionally omitted. Chrome enforces
38
+ * `form-action` on the entire redirect chain of a form submission,
39
+ * not just the immediate target. After login, the OIDC provider
40
+ * redirects through the authorization endpoint and then to the
41
+ * client's `redirect_uri` (a different origin). Chrome blocks
42
+ * this final redirect as a `form-action 'self'` violation, while
43
+ * Firefox only checks the immediate action URL. CSRF tokens are
44
+ * the primary defence against cross-site form attacks; removing
45
+ * `form-action` has negligible security impact given that
46
+ * `script-src 'unsafe-inline'` already allows fetch/XHR exfiltration.
47
+ *
48
+ * Placement:
49
+ * Mount early in the middleware stack — after `errorHandler()` and
50
+ * `requestLogger()` but before any route-specific middleware. This
51
+ * ensures headers are present even on error responses.
52
+ */
53
+ import { config } from '../config/index.js';
54
+ // ---------------------------------------------------------------------------
55
+ // Exported constants — consumed by tests and by other middleware that may
56
+ // need to reference or override specific values.
57
+ // ---------------------------------------------------------------------------
58
+ /**
59
+ * Static security headers applied to every response regardless of
60
+ * content type or route.
61
+ */
62
+ export const STATIC_SECURITY_HEADERS = Object.freeze({
63
+ 'X-Content-Type-Options': 'nosniff',
64
+ 'X-Frame-Options': 'DENY',
65
+ 'Referrer-Policy': 'strict-origin-when-cross-origin',
66
+ 'X-XSS-Protection': '0',
67
+ 'Permissions-Policy': 'camera=(), microphone=(), geolocation=(), payment=()',
68
+ });
69
+ /**
70
+ * Strict Content-Security-Policy for non-HTML (JSON, plain-text) responses.
71
+ * Disallows all resource loading — there is nothing for a browser to render
72
+ * in a JSON API response.
73
+ */
74
+ export const DEFAULT_CSP = "default-src 'none'";
75
+ /**
76
+ * Relaxed Content-Security-Policy for HTML pages (login, consent, 2FA,
77
+ * password reset, invitation, magic-link confirmation, etc.).
78
+ *
79
+ * - `style-src 'unsafe-inline'` — templates use inline `<style>` blocks,
80
+ * inline style attributes, and custom
81
+ * branding CSS injection.
82
+ * - `script-src 'unsafe-inline'` — login.hbs uses an inline `<script>` for
83
+ * dual-method email copying, and
84
+ * two-factor-verify.hbs uses one for
85
+ * OTP/recovery mode toggling.
86
+ * - `frame-ancestors 'none'` — prevents embedding in iframes
87
+ * (modern replacement for X-Frame-Options).
88
+ *
89
+ * `form-action` is intentionally omitted — see module-level doc comment.
90
+ */
91
+ export const HTML_CSP = "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; frame-ancestors 'none'";
92
+ /**
93
+ * HSTS header value — one year, include subdomains.
94
+ * Only emitted when the configured issuer URL uses https.
95
+ */
96
+ export const HSTS_VALUE = 'max-age=31536000; includeSubDomains';
97
+ // ---------------------------------------------------------------------------
98
+ // Middleware factory
99
+ // ---------------------------------------------------------------------------
100
+ /**
101
+ * Determine whether HSTS should be emitted based on the configured
102
+ * issuer URL. Returns `true` when the issuer starts with `https://`.
103
+ *
104
+ * Evaluated once at middleware creation time (issuer doesn't change
105
+ * at runtime).
106
+ */
107
+ function shouldEmitHsts() {
108
+ try {
109
+ return config.issuerBaseUrl.startsWith('https://');
110
+ }
111
+ catch {
112
+ // Config may not be available in test environments — safe to skip.
113
+ return false;
114
+ }
115
+ }
116
+ /**
117
+ * Create the global security-headers Koa middleware.
118
+ *
119
+ * Sets static security headers on every response **before** downstream
120
+ * handlers run, then adjusts the Content-Security-Policy after the
121
+ * response body is produced — if the response is HTML, the CSP is
122
+ * relaxed to allow inline styles and form submissions.
123
+ *
124
+ * @returns Koa middleware function
125
+ */
126
+ export function securityHeaders() {
127
+ const emitHsts = shouldEmitHsts();
128
+ return async function securityHeadersMiddleware(ctx, next) {
129
+ // -----------------------------------------------------------------------
130
+ // Phase 1 — set all static headers before downstream processing.
131
+ // This ensures headers are present even when a downstream handler
132
+ // throws and the error handler generates the final response.
133
+ // -----------------------------------------------------------------------
134
+ for (const [name, value] of Object.entries(STATIC_SECURITY_HEADERS)) {
135
+ ctx.set(name, value);
136
+ }
137
+ // Default strict CSP — overridden post-response for HTML pages.
138
+ ctx.set('Content-Security-Policy', DEFAULT_CSP);
139
+ // HSTS — only when the deployment uses HTTPS.
140
+ if (emitHsts) {
141
+ ctx.set('Strict-Transport-Security', HSTS_VALUE);
142
+ }
143
+ // -----------------------------------------------------------------------
144
+ // Phase 2 — run downstream middleware / route handlers.
145
+ // -----------------------------------------------------------------------
146
+ await next();
147
+ // -----------------------------------------------------------------------
148
+ // Phase 3 — adjust CSP for HTML responses.
149
+ // After the response body and content-type have been set by the route
150
+ // handler, check if the response is HTML and apply the relaxed CSP
151
+ // that allows inline styles and form submissions.
152
+ // -----------------------------------------------------------------------
153
+ const contentType = ctx.response.get('Content-Type') || '';
154
+ if (contentType.includes('text/html')) {
155
+ ctx.set('Content-Security-Policy', HTML_CSP);
156
+ }
157
+ };
158
+ }
159
+ //# sourceMappingURL=security-headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-headers.js","sourceRoot":"","sources":["../../src/middleware/security-headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,8EAA8E;AAC9E,0EAA0E;AAC1E,iDAAiD;AACjD,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAqC,MAAM,CAAC,MAAM,CAAC;IACrF,wBAAwB,EAAE,SAAS;IACnC,iBAAiB,EAAE,MAAM;IACzB,iBAAiB,EAAE,iCAAiC;IACpD,kBAAkB,EAAE,GAAG;IACvB,oBAAoB,EAAE,sDAAsD;CAC7E,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,QAAQ,GACnB,mGAAmG,CAAC;AAEtG;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,qCAAqC,CAAC;AAEhE,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;QACnE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAElC,OAAO,KAAK,UAAU,yBAAyB,CAAC,GAAG,EAAE,IAAI;QACvD,0EAA0E;QAC1E,iEAAiE;QACjE,kEAAkE;QAClE,6DAA6D;QAC7D,0EAA0E;QAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;QAED,gEAAgE;QAChE,GAAG,CAAC,GAAG,CAAC,yBAAyB,EAAE,WAAW,CAAC,CAAC;QAEhD,8CAA8C;QAC9C,IAAI,QAAQ,EAAE,CAAC;YACb,GAAG,CAAC,GAAG,CAAC,2BAA2B,EAAE,UAAU,CAAC,CAAC;QACnD,CAAC;QAED,0EAA0E;QAC1E,wDAAwD;QACxD,0EAA0E;QAC1E,MAAM,IAAI,EAAE,CAAC;QAEb,0EAA0E;QAC1E,2CAA2C;QAC3C,sEAAsE;QACtE,mEAAmE;QACnE,kDAAkD;QAClD,0EAA0E;QAC1E,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC3D,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,GAAG,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Multi-tenant resolver middleware.
3
+ *
4
+ * Extracts the organization slug from the URL path, resolves the
5
+ * organization using Redis cache (with DB fallback), validates the
6
+ * organization status, and sets tenant context on ctx.state.
7
+ *
8
+ * This middleware is applied to routes under /:orgSlug/* — it does NOT
9
+ * apply to root-level routes like /health.
10
+ *
11
+ * Resolution flow:
12
+ * 1. Extract orgSlug from route params
13
+ * 2. Check Redis cache: getCachedOrganizationBySlug(orgSlug)
14
+ * 3. If cache miss, query DB: findOrganizationBySlug(orgSlug)
15
+ * 4. If found from DB, cache it: cacheOrganization(org)
16
+ * 5. Validate status:
17
+ * - archived → 404 "Organization not found"
18
+ * - suspended → 403 "Organization is suspended"
19
+ * - active → continue
20
+ * 6. Set ctx.state.organization (full Organization object)
21
+ * 7. Set ctx.state.issuer
22
+ *
23
+ * Returns:
24
+ * - 404 if organization not found or archived
25
+ * - 403 if organization is suspended
26
+ */
27
+ import type { Middleware } from 'koa';
28
+ /**
29
+ * Create the tenant resolver middleware.
30
+ *
31
+ * Expects the route to have an `:orgSlug` parameter (e.g., `/:orgSlug/*`).
32
+ * Resolves the organization via cache-first strategy and validates status.
33
+ *
34
+ * @returns Koa middleware function
35
+ */
36
+ export declare function tenantResolver(): Middleware;
37
+ //# sourceMappingURL=tenant-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-resolver.d.ts","sourceRoot":"","sources":["../../src/middleware/tenant-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAStC;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAyC3C"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Multi-tenant resolver middleware.
3
+ *
4
+ * Extracts the organization slug from the URL path, resolves the
5
+ * organization using Redis cache (with DB fallback), validates the
6
+ * organization status, and sets tenant context on ctx.state.
7
+ *
8
+ * This middleware is applied to routes under /:orgSlug/* — it does NOT
9
+ * apply to root-level routes like /health.
10
+ *
11
+ * Resolution flow:
12
+ * 1. Extract orgSlug from route params
13
+ * 2. Check Redis cache: getCachedOrganizationBySlug(orgSlug)
14
+ * 3. If cache miss, query DB: findOrganizationBySlug(orgSlug)
15
+ * 4. If found from DB, cache it: cacheOrganization(org)
16
+ * 5. Validate status:
17
+ * - archived → 404 "Organization not found"
18
+ * - suspended → 403 "Organization is suspended"
19
+ * - active → continue
20
+ * 6. Set ctx.state.organization (full Organization object)
21
+ * 7. Set ctx.state.issuer
22
+ *
23
+ * Returns:
24
+ * - 404 if organization not found or archived
25
+ * - 403 if organization is suspended
26
+ */
27
+ import { config } from '../config/index.js';
28
+ import { getCachedOrganizationBySlug, cacheOrganization, } from '../organizations/cache.js';
29
+ import { findOrganizationBySlug } from '../organizations/repository.js';
30
+ /**
31
+ * Create the tenant resolver middleware.
32
+ *
33
+ * Expects the route to have an `:orgSlug` parameter (e.g., `/:orgSlug/*`).
34
+ * Resolves the organization via cache-first strategy and validates status.
35
+ *
36
+ * @returns Koa middleware function
37
+ */
38
+ export function tenantResolver() {
39
+ return async (ctx, next) => {
40
+ const orgSlug = ctx.params?.orgSlug;
41
+ if (!orgSlug) {
42
+ ctx.throw(404, 'Organization not found');
43
+ }
44
+ // 1. Try Redis cache first
45
+ let org = await getCachedOrganizationBySlug(orgSlug);
46
+ // 2. Cache miss → query database (returns all statuses)
47
+ if (!org) {
48
+ org = await findOrganizationBySlug(orgSlug);
49
+ // 3. Cache the result for subsequent requests
50
+ if (org) {
51
+ await cacheOrganization(org);
52
+ }
53
+ }
54
+ // 4. Not found at all
55
+ if (!org) {
56
+ return ctx.throw(404, 'Organization not found');
57
+ }
58
+ // 5. Status-dependent responses
59
+ if (org.status === 'archived') {
60
+ return ctx.throw(404, 'Organization not found');
61
+ }
62
+ if (org.status === 'suspended') {
63
+ return ctx.throw(403, 'Organization is suspended');
64
+ }
65
+ // 6. Set tenant context for downstream middleware and OIDC provider
66
+ ctx.state.organization = org;
67
+ ctx.state.issuer = `${config.issuerBaseUrl}/${org.slug}`;
68
+ await next();
69
+ };
70
+ }
71
+ //# sourceMappingURL=tenant-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-resolver.js","sourceRoot":"","sources":["../../src/middleware/tenant-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EACL,2BAA2B,EAC3B,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAGxE;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;QAEpC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;QAC3C,CAAC;QAED,2BAA2B;QAC3B,IAAI,GAAG,GAAwB,MAAM,2BAA2B,CAAC,OAAO,CAAC,CAAC;QAE1E,wDAAwD;QACxD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,MAAM,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAE5C,8CAA8C;YAC9C,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;QAClD,CAAC;QAED,gCAAgC;QAChC,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,wBAAwB,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,2BAA2B,CAAC,CAAC;QACrD,CAAC;QAED,oEAAoE;QACpE,GAAG,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC;QAC7B,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QAEzD,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Token and introspection endpoint rate limiter middleware.
3
+ *
4
+ * Protects the OAuth token endpoint (`POST /:orgSlug/oidc/token`) and
5
+ * token introspection endpoint (`POST /:orgSlug/oidc/token/introspection`)
6
+ * against abuse: client-credentials flooding, authorization-code
7
+ * brute-forcing, token enumeration, and general endpoint spam.
8
+ *
9
+ * Rate limiting is per-IP + per-client_id composite key. If `client_id`
10
+ * is not present in the request body (e.g. `client_secret_basic` auth
11
+ * sends credentials in the `Authorization` header), the key falls back
12
+ * to `unknown` — all such requests from the same IP share one counter.
13
+ *
14
+ * Reuses the existing `checkRateLimit()` infrastructure from
15
+ * `src/auth/rate-limiter.ts` which provides Redis INCR+EXPIRE sliding
16
+ * window and graceful degradation on Redis failure.
17
+ *
18
+ * Placement: mount as global middleware **before** the OIDC provider
19
+ * router in `src/server.ts`. The path regex ensures only matching
20
+ * requests are rate-limited — all other paths pass through untouched.
21
+ *
22
+ * @module middleware/token-rate-limiter
23
+ */
24
+ import type { Middleware } from 'koa';
25
+ import type { RateLimitConfig } from '../auth/rate-limiter.js';
26
+ /**
27
+ * Regex matching the OIDC token endpoint path.
28
+ *
29
+ * Pattern: `/<orgSlug>/oidc/token` where orgSlug starts with a
30
+ * lowercase alphanumeric character followed by zero or more lowercase
31
+ * alphanumeric or hyphen characters.
32
+ *
33
+ * Matches: `/acme/oidc/token`, `/my-org/oidc/token`
34
+ * Rejects: `/api/admin/something`, `/acme/oidc/token/extra`
35
+ */
36
+ export declare const TOKEN_PATH_REGEX: RegExp;
37
+ /**
38
+ * Rate limit configuration for the token endpoint.
39
+ *
40
+ * 30 requests per 5-minute window — generous enough for legitimate
41
+ * applications (SPAs refreshing tokens, server-side token exchanges)
42
+ * while catching automated abuse.
43
+ */
44
+ export declare const TOKEN_RATE_LIMIT: RateLimitConfig;
45
+ /**
46
+ * Create the token endpoint rate limiter middleware.
47
+ *
48
+ * Only intercepts `POST` requests to paths matching `TOKEN_PATH_REGEX`.
49
+ * Sets informational `X-RateLimit-*` headers on every token response
50
+ * and returns a `429` with an OAuth-format error body when the limit
51
+ * is exceeded.
52
+ *
53
+ * @returns Koa middleware that rate-limits the OIDC token endpoint
54
+ */
55
+ export declare function tokenRateLimiter(): Middleware;
56
+ /**
57
+ * Regex matching the OIDC token introspection endpoint path.
58
+ *
59
+ * Pattern: `/<orgSlug>/oidc/token/introspection` where orgSlug uses
60
+ * the same slug format as TOKEN_PATH_REGEX.
61
+ *
62
+ * Matches: `/acme/oidc/token/introspection`, `/my-org/oidc/token/introspection`
63
+ * Rejects: `/acme/oidc/token`, `/api/admin/introspection`
64
+ */
65
+ export declare const INTROSPECTION_PATH_REGEX: RegExp;
66
+ /**
67
+ * Rate limit configuration for the introspection endpoint.
68
+ *
69
+ * 100 requests per 60-second window — higher than the token endpoint
70
+ * because introspection is used by resource servers to validate tokens
71
+ * on every API call. The higher limit accommodates legitimate traffic
72
+ * while still preventing token enumeration attacks.
73
+ */
74
+ export declare const INTROSPECTION_RATE_LIMIT: RateLimitConfig;
75
+ /**
76
+ * Create the introspection endpoint rate limiter middleware.
77
+ *
78
+ * Only intercepts `POST` requests to paths matching
79
+ * `INTROSPECTION_PATH_REGEX`. Sets informational `X-RateLimit-*`
80
+ * headers and returns a `429` with an OAuth-format error body when
81
+ * the limit is exceeded.
82
+ *
83
+ * Key format: `ratelimit:introspect:{ip}:{clientId}` — composite key
84
+ * per-IP + per-client_id for granular rate limiting.
85
+ *
86
+ * @returns Koa middleware that rate-limits the OIDC introspection endpoint
87
+ */
88
+ export declare function introspectionRateLimiter(): Middleware;
89
+ //# sourceMappingURL=token-rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-rate-limiter.d.ts","sourceRoot":"","sources":["../../src/middleware/token-rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO/D;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,QAAwC,CAAC;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAG9B,CAAC;AAMF;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAwD7C;AAMD;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,QAAuD,CAAC;AAE7F;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,EAAE,eAGtC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,IAAI,UAAU,CAqDrD"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Token and introspection endpoint rate limiter middleware.
3
+ *
4
+ * Protects the OAuth token endpoint (`POST /:orgSlug/oidc/token`) and
5
+ * token introspection endpoint (`POST /:orgSlug/oidc/token/introspection`)
6
+ * against abuse: client-credentials flooding, authorization-code
7
+ * brute-forcing, token enumeration, and general endpoint spam.
8
+ *
9
+ * Rate limiting is per-IP + per-client_id composite key. If `client_id`
10
+ * is not present in the request body (e.g. `client_secret_basic` auth
11
+ * sends credentials in the `Authorization` header), the key falls back
12
+ * to `unknown` — all such requests from the same IP share one counter.
13
+ *
14
+ * Reuses the existing `checkRateLimit()` infrastructure from
15
+ * `src/auth/rate-limiter.ts` which provides Redis INCR+EXPIRE sliding
16
+ * window and graceful degradation on Redis failure.
17
+ *
18
+ * Placement: mount as global middleware **before** the OIDC provider
19
+ * router in `src/server.ts`. The path regex ensures only matching
20
+ * requests are rate-limited — all other paths pass through untouched.
21
+ *
22
+ * @module middleware/token-rate-limiter
23
+ */
24
+ import { checkRateLimit } from '../auth/rate-limiter.js';
25
+ import { logger } from '../lib/logger.js';
26
+ // ---------------------------------------------------------------------------
27
+ // Constants — exported for test assertions and documentation
28
+ // ---------------------------------------------------------------------------
29
+ /**
30
+ * Regex matching the OIDC token endpoint path.
31
+ *
32
+ * Pattern: `/<orgSlug>/oidc/token` where orgSlug starts with a
33
+ * lowercase alphanumeric character followed by zero or more lowercase
34
+ * alphanumeric or hyphen characters.
35
+ *
36
+ * Matches: `/acme/oidc/token`, `/my-org/oidc/token`
37
+ * Rejects: `/api/admin/something`, `/acme/oidc/token/extra`
38
+ */
39
+ export const TOKEN_PATH_REGEX = /^\/[a-z0-9][a-z0-9-]*\/oidc\/token$/;
40
+ /**
41
+ * Rate limit configuration for the token endpoint.
42
+ *
43
+ * 30 requests per 5-minute window — generous enough for legitimate
44
+ * applications (SPAs refreshing tokens, server-side token exchanges)
45
+ * while catching automated abuse.
46
+ */
47
+ export const TOKEN_RATE_LIMIT = {
48
+ max: 30,
49
+ windowSeconds: 300,
50
+ };
51
+ // ---------------------------------------------------------------------------
52
+ // Middleware factory
53
+ // ---------------------------------------------------------------------------
54
+ /**
55
+ * Create the token endpoint rate limiter middleware.
56
+ *
57
+ * Only intercepts `POST` requests to paths matching `TOKEN_PATH_REGEX`.
58
+ * Sets informational `X-RateLimit-*` headers on every token response
59
+ * and returns a `429` with an OAuth-format error body when the limit
60
+ * is exceeded.
61
+ *
62
+ * @returns Koa middleware that rate-limits the OIDC token endpoint
63
+ */
64
+ export function tokenRateLimiter() {
65
+ return async function tokenRateLimiterMiddleware(ctx, next) {
66
+ // Only rate-limit POST to the token endpoint — GET, OPTIONS, etc.
67
+ // and all non-token paths pass through immediately.
68
+ if (ctx.method !== 'POST' || !TOKEN_PATH_REGEX.test(ctx.path)) {
69
+ return next();
70
+ }
71
+ // Extract client_id from the parsed request body if available.
72
+ // The selective bodyParser in server.ts excludes OIDC routes, so
73
+ // ctx.request.body may be empty when this middleware runs.
74
+ // Fall back to 'unknown' — all unidentified clients from the same
75
+ // IP share a single rate limit counter, which is acceptable.
76
+ const body = ctx.request.body;
77
+ const clientId = body?.client_id;
78
+ const clientKey = typeof clientId === 'string' && clientId.length > 0
79
+ ? clientId
80
+ : 'unknown';
81
+ // Composite key: per-IP + per-client_id for granular rate limiting
82
+ const key = `ratelimit:token:${ctx.ip}:${clientKey}`;
83
+ const result = await checkRateLimit(key, TOKEN_RATE_LIMIT);
84
+ // Informational headers on all responses — helps legitimate clients
85
+ // monitor their usage and implement backoff strategies.
86
+ ctx.set('X-RateLimit-Limit', String(TOKEN_RATE_LIMIT.max));
87
+ ctx.set('X-RateLimit-Remaining', String(result.remaining));
88
+ if (!result.allowed) {
89
+ logger.warn({
90
+ action: 'token_rate_limit_exceeded',
91
+ ip: ctx.ip,
92
+ clientId: clientKey,
93
+ path: ctx.path,
94
+ }, 'Token endpoint rate limit exceeded');
95
+ ctx.status = 429;
96
+ ctx.set('Retry-After', String(result.retryAfter));
97
+ // OAuth 2.0 error format — clients that parse token endpoint
98
+ // errors can handle this structured response.
99
+ ctx.body = {
100
+ error: 'rate_limit_exceeded',
101
+ error_description: 'Too many token requests. Please try again later.',
102
+ retry_after: result.retryAfter,
103
+ };
104
+ return;
105
+ }
106
+ return next();
107
+ };
108
+ }
109
+ // ---------------------------------------------------------------------------
110
+ // Introspection endpoint rate limiter
111
+ // ---------------------------------------------------------------------------
112
+ /**
113
+ * Regex matching the OIDC token introspection endpoint path.
114
+ *
115
+ * Pattern: `/<orgSlug>/oidc/token/introspection` where orgSlug uses
116
+ * the same slug format as TOKEN_PATH_REGEX.
117
+ *
118
+ * Matches: `/acme/oidc/token/introspection`, `/my-org/oidc/token/introspection`
119
+ * Rejects: `/acme/oidc/token`, `/api/admin/introspection`
120
+ */
121
+ export const INTROSPECTION_PATH_REGEX = /^\/[a-z0-9][a-z0-9-]*\/oidc\/token\/introspection$/;
122
+ /**
123
+ * Rate limit configuration for the introspection endpoint.
124
+ *
125
+ * 100 requests per 60-second window — higher than the token endpoint
126
+ * because introspection is used by resource servers to validate tokens
127
+ * on every API call. The higher limit accommodates legitimate traffic
128
+ * while still preventing token enumeration attacks.
129
+ */
130
+ export const INTROSPECTION_RATE_LIMIT = {
131
+ max: 100,
132
+ windowSeconds: 60,
133
+ };
134
+ /**
135
+ * Create the introspection endpoint rate limiter middleware.
136
+ *
137
+ * Only intercepts `POST` requests to paths matching
138
+ * `INTROSPECTION_PATH_REGEX`. Sets informational `X-RateLimit-*`
139
+ * headers and returns a `429` with an OAuth-format error body when
140
+ * the limit is exceeded.
141
+ *
142
+ * Key format: `ratelimit:introspect:{ip}:{clientId}` — composite key
143
+ * per-IP + per-client_id for granular rate limiting.
144
+ *
145
+ * @returns Koa middleware that rate-limits the OIDC introspection endpoint
146
+ */
147
+ export function introspectionRateLimiter() {
148
+ return async function introspectionRateLimiterMiddleware(ctx, next) {
149
+ // Only rate-limit POST to the introspection endpoint.
150
+ if (ctx.method !== 'POST' || !INTROSPECTION_PATH_REGEX.test(ctx.path)) {
151
+ return next();
152
+ }
153
+ // Extract client_id from the parsed request body if available.
154
+ // Introspection requests carry client credentials — client_id may
155
+ // be in the body (client_secret_post) or absent (client_secret_basic).
156
+ const body = ctx.request.body;
157
+ const clientId = body?.client_id;
158
+ const clientKey = typeof clientId === 'string' && clientId.length > 0
159
+ ? clientId
160
+ : 'unknown';
161
+ // Composite key: per-IP + per-client_id — separate namespace from
162
+ // the token endpoint to keep counters independent.
163
+ const key = `ratelimit:introspect:${ctx.ip}:${clientKey}`;
164
+ const result = await checkRateLimit(key, INTROSPECTION_RATE_LIMIT);
165
+ // Informational headers on all matched responses.
166
+ ctx.set('X-RateLimit-Limit', String(INTROSPECTION_RATE_LIMIT.max));
167
+ ctx.set('X-RateLimit-Remaining', String(result.remaining));
168
+ if (!result.allowed) {
169
+ logger.warn({
170
+ action: 'introspection_rate_limit_exceeded',
171
+ ip: ctx.ip,
172
+ clientId: clientKey,
173
+ path: ctx.path,
174
+ }, 'Introspection endpoint rate limit exceeded');
175
+ ctx.status = 429;
176
+ ctx.set('Retry-After', String(result.retryAfter));
177
+ // OAuth 2.0 error format — resource servers parsing introspection
178
+ // errors can handle this structured response.
179
+ ctx.body = {
180
+ error: 'rate_limit_exceeded',
181
+ error_description: 'Too many introspection requests. Please try again later.',
182
+ retry_after: result.retryAfter,
183
+ };
184
+ return;
185
+ }
186
+ return next();
187
+ };
188
+ }
189
+ //# sourceMappingURL=token-rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-rate-limiter.js","sourceRoot":"","sources":["../../src/middleware/token-rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Account finder for node-oidc-provider.
3
+ *
4
+ * Maps user records from the database to OIDC account objects with a
5
+ * claims() method. The provider calls findAccount when it needs user
6
+ * information for ID tokens, userinfo endpoint responses, etc.
7
+ *
8
+ * This implementation delegates to the user service for lookup and
9
+ * the claims builder for scope-based claims mapping. The user must
10
+ * be active to be returned — non-active users get undefined (no account).
11
+ *
12
+ * Claims flow:
13
+ * 1. buildUserClaims(user, scopes) → standard OIDC claims (sub, name, email...)
14
+ * 2. buildRoleClaims(userId) → role slugs array (cache-first)
15
+ * 3. buildPermissionClaims(userId) → permission slugs array (cache-first)
16
+ * 4. buildCustomClaims(userId, appId, tokenType) → custom per-app claims
17
+ *
18
+ * The applicationId for custom claims is resolved from the OIDC client
19
+ * context. If unavailable (e.g., no client context), custom claims are
20
+ * skipped gracefully.
21
+ *
22
+ * @see users/service.ts — User lookup for OIDC
23
+ * @see users/claims.ts — Standard OIDC claims builder
24
+ * @see rbac/user-role-service.ts — RBAC claims builders
25
+ * @see custom-claims/service.ts — Custom claims builder
26
+ */
27
+ /** OIDC Account object — returned by findAccount, used by the provider */
28
+ export interface OidcAccount {
29
+ /** The subject identifier (user UUID) */
30
+ accountId: string;
31
+ /**
32
+ * Return OIDC claims for the user.
33
+ * @param use - Token type ('id_token' or 'userinfo')
34
+ * @param scope - Granted scopes (space-separated)
35
+ * @returns Object with OIDC Standard Claims + RBAC + custom claims
36
+ */
37
+ claims: (use: string, scope: string) => Promise<Record<string, unknown>>;
38
+ }
39
+ /**
40
+ * Find an OIDC account by subject identifier (user ID).
41
+ *
42
+ * Delegates to the user service's findUserForOidc which returns
43
+ * active users only. Returns an account object with a claims() method
44
+ * that builds scope-filtered OIDC Standard Claims merged with RBAC
45
+ * role/permission claims and per-application custom claims.
46
+ *
47
+ * @param ctx - Koa context with OIDC extensions (used to resolve client/app context)
48
+ * @param sub - The subject identifier (user UUID)
49
+ * @returns Account object with claims() method, or undefined if not found
50
+ */
51
+ export declare function findAccount(ctx: unknown, sub: string): Promise<OidcAccount | undefined>;
52
+ //# sourceMappingURL=account-finder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-finder.d.ts","sourceRoot":"","sources":["../../src/oidc/account-finder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AASH,0EAA0E;AAC1E,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAmDlC"}