@hilbras/keystone 1.6.0 → 2.5.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 (604) hide show
  1. package/CHANGELOG.md +625 -0
  2. package/README.md +198 -50
  3. package/dist/cli.js +25 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +23 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +53 -8
  8. package/dist/config.js.map +1 -1
  9. package/dist/container.d.ts +4 -1
  10. package/dist/container.d.ts.map +1 -1
  11. package/dist/container.js.map +1 -1
  12. package/dist/db/migrations/0008_flashy_firestar.sql +5 -0
  13. package/dist/db/migrations/0009_daffy_changeling.sql +1 -0
  14. package/dist/db/migrations/0010_wealthy_shadow_king.sql +37 -0
  15. package/dist/db/migrations/0011_overrated_vector.sql +18 -0
  16. package/dist/db/migrations/0012_brave_darkhawk.sql +28 -0
  17. package/dist/db/migrations/0013_wonderful_chimera.sql +5 -0
  18. package/dist/db/migrations/0014_magical_morph.sql +48 -0
  19. package/dist/db/migrations/0015_chief_vargas.sql +7 -0
  20. package/dist/db/migrations/0016_gorgeous_charles_xavier.sql +5 -0
  21. package/dist/db/migrations/0017_flashy_nekra.sql +1 -0
  22. package/{src/db/migrations/meta/0007_snapshot.json → dist/db/migrations/meta/0008_snapshot.json} +136 -32
  23. package/{src/db/migrations/meta/0006_snapshot.json → dist/db/migrations/meta/0009_snapshot.json} +359 -30
  24. package/{src/db/migrations/meta/0005_snapshot.json → dist/db/migrations/meta/0010_snapshot.json} +459 -29
  25. package/{src/db/migrations/meta/0004_snapshot.json → dist/db/migrations/meta/0011_snapshot.json} +594 -30
  26. package/dist/db/migrations/meta/0012_snapshot.json +3891 -0
  27. package/dist/db/migrations/meta/0013_snapshot.json +3919 -0
  28. package/dist/db/migrations/meta/0014_snapshot.json +4311 -0
  29. package/dist/db/migrations/meta/0015_snapshot.json +4340 -0
  30. package/dist/db/migrations/meta/0016_snapshot.json +4363 -0
  31. package/dist/db/migrations/meta/0017_snapshot.json +4370 -0
  32. package/dist/db/migrations/meta/_journal.json +70 -0
  33. package/dist/db/reencryptOidcSecrets.d.ts +2 -0
  34. package/dist/db/reencryptOidcSecrets.d.ts.map +1 -0
  35. package/dist/db/reencryptOidcSecrets.js +41 -0
  36. package/dist/db/reencryptOidcSecrets.js.map +1 -0
  37. package/dist/db/schema.d.ts +2693 -88
  38. package/dist/db/schema.d.ts.map +1 -1
  39. package/dist/db/schema.js +157 -4
  40. package/dist/db/schema.js.map +1 -1
  41. package/dist/db/seed.js +67 -40
  42. package/dist/db/seed.js.map +1 -1
  43. package/dist/di.d.ts.map +1 -1
  44. package/dist/di.js +11 -3
  45. package/dist/di.js.map +1 -1
  46. package/dist/index.d.ts +2 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +34 -3
  49. package/dist/index.js.map +1 -1
  50. package/dist/lib/errors.d.ts +2 -1
  51. package/dist/lib/errors.d.ts.map +1 -1
  52. package/dist/lib/errors.js +10 -0
  53. package/dist/lib/errors.js.map +1 -1
  54. package/dist/plugins/appContext.d.ts.map +1 -1
  55. package/dist/plugins/appContext.js +3 -12
  56. package/dist/plugins/appContext.js.map +1 -1
  57. package/dist/plugins/audit.d.ts.map +1 -1
  58. package/dist/plugins/audit.js +26 -6
  59. package/dist/plugins/audit.js.map +1 -1
  60. package/dist/plugins/auth.d.ts.map +1 -1
  61. package/dist/plugins/auth.js +32 -7
  62. package/dist/plugins/auth.js.map +1 -1
  63. package/dist/plugins/headerSanitization.d.ts +15 -0
  64. package/dist/plugins/headerSanitization.d.ts.map +1 -0
  65. package/dist/plugins/headerSanitization.js +39 -0
  66. package/dist/plugins/headerSanitization.js.map +1 -0
  67. package/dist/plugins/metrics.d.ts.map +1 -1
  68. package/dist/plugins/mtls.d.ts +21 -2
  69. package/dist/plugins/mtls.d.ts.map +1 -1
  70. package/dist/plugins/mtls.js +94 -47
  71. package/dist/plugins/mtls.js.map +1 -1
  72. package/dist/plugins/permissions.d.ts.map +1 -1
  73. package/dist/plugins/permissions.js +29 -9
  74. package/dist/plugins/permissions.js.map +1 -1
  75. package/dist/plugins/rateLimit.d.ts +16 -0
  76. package/dist/plugins/rateLimit.d.ts.map +1 -1
  77. package/dist/plugins/rateLimit.js +16 -3
  78. package/dist/plugins/rateLimit.js.map +1 -1
  79. package/dist/plugins/requestLogger.d.ts.map +1 -1
  80. package/dist/repositories/apiKey.d.ts.map +1 -1
  81. package/dist/repositories/application.d.ts +1 -1
  82. package/dist/repositories/application.d.ts.map +1 -1
  83. package/dist/repositories/application.js +9 -3
  84. package/dist/repositories/application.js.map +1 -1
  85. package/dist/repositories/audit.d.ts.map +1 -1
  86. package/dist/repositories/index.d.ts +3 -0
  87. package/dist/repositories/index.d.ts.map +1 -1
  88. package/dist/repositories/index.js +3 -0
  89. package/dist/repositories/index.js.map +1 -1
  90. package/dist/repositories/mfaChallenge.d.ts +23 -0
  91. package/dist/repositories/mfaChallenge.d.ts.map +1 -0
  92. package/dist/repositories/mfaChallenge.js +71 -0
  93. package/dist/repositories/mfaChallenge.js.map +1 -0
  94. package/dist/repositories/oidcConnection.d.ts +27 -43
  95. package/dist/repositories/oidcConnection.d.ts.map +1 -1
  96. package/dist/repositories/oidcConnection.js +15 -6
  97. package/dist/repositories/oidcConnection.js.map +1 -1
  98. package/dist/repositories/organization.d.ts +9 -9
  99. package/dist/repositories/organization.d.ts.map +1 -1
  100. package/dist/repositories/organization.js +91 -37
  101. package/dist/repositories/organization.js.map +1 -1
  102. package/dist/repositories/permission.d.ts.map +1 -1
  103. package/dist/repositories/permission.js +27 -5
  104. package/dist/repositories/permission.js.map +1 -1
  105. package/dist/repositories/samlConnection.d.ts +28 -28
  106. package/dist/repositories/samlConnection.d.ts.map +1 -1
  107. package/dist/repositories/samlConnection.js +12 -4
  108. package/dist/repositories/samlConnection.js.map +1 -1
  109. package/dist/repositories/scimConnection.d.ts +38 -0
  110. package/dist/repositories/scimConnection.d.ts.map +1 -0
  111. package/dist/repositories/scimConnection.js +123 -0
  112. package/dist/repositories/scimConnection.js.map +1 -0
  113. package/dist/repositories/scimGroup.d.ts +36 -0
  114. package/dist/repositories/scimGroup.d.ts.map +1 -0
  115. package/dist/repositories/scimGroup.js +113 -0
  116. package/dist/repositories/scimGroup.js.map +1 -0
  117. package/dist/repositories/session.d.ts +24 -13
  118. package/dist/repositories/session.d.ts.map +1 -1
  119. package/dist/repositories/session.js +13 -1
  120. package/dist/repositories/session.js.map +1 -1
  121. package/dist/repositories/types.d.ts +117 -6
  122. package/dist/repositories/types.d.ts.map +1 -1
  123. package/dist/repositories/types.js +7 -1
  124. package/dist/repositories/types.js.map +1 -1
  125. package/dist/repositories/user.d.ts +23 -1
  126. package/dist/repositories/user.d.ts.map +1 -1
  127. package/dist/repositories/user.js +180 -4
  128. package/dist/repositories/user.js.map +1 -1
  129. package/dist/routes/admin/billing.js +4 -4
  130. package/dist/routes/admin/billing.js.map +1 -1
  131. package/dist/routes/admin/helpers.d.ts +16 -20
  132. package/dist/routes/admin/helpers.d.ts.map +1 -1
  133. package/dist/routes/admin/helpers.js +53 -10
  134. package/dist/routes/admin/helpers.js.map +1 -1
  135. package/dist/routes/admin/organizations.d.ts.map +1 -1
  136. package/dist/routes/admin/organizations.js +105 -69
  137. package/dist/routes/admin/organizations.js.map +1 -1
  138. package/dist/routes/admin/permissions.d.ts.map +1 -1
  139. package/dist/routes/admin/permissions.js +48 -14
  140. package/dist/routes/admin/permissions.js.map +1 -1
  141. package/dist/routes/admin/platform.d.ts.map +1 -1
  142. package/dist/routes/admin/platform.js +86 -35
  143. package/dist/routes/admin/platform.js.map +1 -1
  144. package/dist/routes/admin/sso.d.ts.map +1 -1
  145. package/dist/routes/admin/sso.js +143 -12
  146. package/dist/routes/admin/sso.js.map +1 -1
  147. package/dist/routes/admin/webhooks.js +8 -8
  148. package/dist/routes/admin/webhooks.js.map +1 -1
  149. package/dist/routes/apiKeys.d.ts.map +1 -1
  150. package/dist/routes/apiKeys.js +23 -5
  151. package/dist/routes/apiKeys.js.map +1 -1
  152. package/dist/routes/auth.d.ts.map +1 -1
  153. package/dist/routes/auth.js +112 -22
  154. package/dist/routes/auth.js.map +1 -1
  155. package/dist/routes/authz.d.ts.map +1 -1
  156. package/dist/routes/authz.js +16 -4
  157. package/dist/routes/authz.js.map +1 -1
  158. package/dist/routes/config.d.ts.map +1 -1
  159. package/dist/routes/config.js +16 -14
  160. package/dist/routes/config.js.map +1 -1
  161. package/dist/routes/federation.d.ts.map +1 -1
  162. package/dist/routes/federation.js +17 -3
  163. package/dist/routes/federation.js.map +1 -1
  164. package/dist/routes/magicLinks.d.ts.map +1 -1
  165. package/dist/routes/magicLinks.js +15 -3
  166. package/dist/routes/magicLinks.js.map +1 -1
  167. package/dist/routes/oauth.d.ts.map +1 -1
  168. package/dist/routes/oauth.js +60 -5
  169. package/dist/routes/oauth.js.map +1 -1
  170. package/dist/routes/oauth2.d.ts.map +1 -1
  171. package/dist/routes/oauth2.js +188 -22
  172. package/dist/routes/oauth2.js.map +1 -1
  173. package/dist/routes/oidcEnterprise.d.ts.map +1 -1
  174. package/dist/routes/oidcEnterprise.js +67 -21
  175. package/dist/routes/oidcEnterprise.js.map +1 -1
  176. package/dist/routes/password.d.ts.map +1 -1
  177. package/dist/routes/password.js.map +1 -1
  178. package/dist/routes/profile.js +4 -4
  179. package/dist/routes/profile.js.map +1 -1
  180. package/dist/routes/saml.d.ts +33 -0
  181. package/dist/routes/saml.d.ts.map +1 -1
  182. package/dist/routes/saml.js +217 -12
  183. package/dist/routes/saml.js.map +1 -1
  184. package/dist/routes/scim.d.ts +13 -0
  185. package/dist/routes/scim.d.ts.map +1 -1
  186. package/dist/routes/scim.js +885 -110
  187. package/dist/routes/scim.js.map +1 -1
  188. package/dist/routes/sdk.d.ts.map +1 -1
  189. package/dist/routes/sdk.js +24 -8
  190. package/dist/routes/sdk.js.map +1 -1
  191. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  192. package/dist/routes/serviceAccounts.js +63 -2
  193. package/dist/routes/serviceAccounts.js.map +1 -1
  194. package/dist/routes/setup.d.ts.map +1 -1
  195. package/dist/routes/setup.js +15 -16
  196. package/dist/routes/setup.js.map +1 -1
  197. package/dist/routes/smsOtp.js +1 -1
  198. package/dist/routes/smsOtp.js.map +1 -1
  199. package/dist/routes/totp.d.ts.map +1 -1
  200. package/dist/routes/totp.js +112 -23
  201. package/dist/routes/totp.js.map +1 -1
  202. package/dist/routes/webauthn.d.ts.map +1 -1
  203. package/dist/routes/webauthn.js +44 -8
  204. package/dist/routes/webauthn.js.map +1 -1
  205. package/dist/routes/workflows.d.ts.map +1 -1
  206. package/dist/routes/workflows.js +58 -25
  207. package/dist/routes/workflows.js.map +1 -1
  208. package/dist/sdk/index.d.ts.map +1 -1
  209. package/dist/sdk/index.js +141 -40
  210. package/dist/sdk/index.js.map +1 -1
  211. package/dist/sdk/types.d.ts +64 -30
  212. package/dist/sdk/types.d.ts.map +1 -1
  213. package/dist/services/application/authentication.d.ts +39 -1
  214. package/dist/services/application/authentication.d.ts.map +1 -1
  215. package/dist/services/application/authentication.js +43 -1
  216. package/dist/services/application/authentication.js.map +1 -1
  217. package/dist/services/application/identity.d.ts +10 -7
  218. package/dist/services/application/identity.d.ts.map +1 -1
  219. package/dist/services/application/identity.js +13 -10
  220. package/dist/services/application/identity.js.map +1 -1
  221. package/dist/services/application/organization.d.ts +16 -8
  222. package/dist/services/application/organization.d.ts.map +1 -1
  223. package/dist/services/application/organization.js +160 -12
  224. package/dist/services/application/organization.js.map +1 -1
  225. package/dist/services/applications.js +2 -2
  226. package/dist/services/applications.js.map +1 -1
  227. package/dist/services/audit.d.ts +1 -0
  228. package/dist/services/audit.d.ts.map +1 -1
  229. package/dist/services/audit.js +13 -0
  230. package/dist/services/audit.js.map +1 -1
  231. package/dist/services/cache.d.ts.map +1 -1
  232. package/dist/services/configuration/profiles.d.ts +4 -0
  233. package/dist/services/configuration/profiles.d.ts.map +1 -1
  234. package/dist/services/configuration/profiles.js +50 -0
  235. package/dist/services/configuration/profiles.js.map +1 -1
  236. package/dist/services/configuration.d.ts.map +1 -1
  237. package/dist/services/configuration.js.map +1 -1
  238. package/dist/services/connectors/google.d.ts +18 -1
  239. package/dist/services/connectors/google.d.ts.map +1 -1
  240. package/dist/services/connectors/google.js +27 -4
  241. package/dist/services/connectors/google.js.map +1 -1
  242. package/dist/services/connectors/oidc.d.ts +14 -2
  243. package/dist/services/connectors/oidc.d.ts.map +1 -1
  244. package/dist/services/connectors/oidc.js +35 -6
  245. package/dist/services/connectors/oidc.js.map +1 -1
  246. package/dist/services/connectors/types.d.ts +13 -1
  247. package/dist/services/connectors/types.d.ts.map +1 -1
  248. package/dist/services/connectors/zitadel.d.ts.map +1 -1
  249. package/dist/services/connectors/zitadel.js +4 -3
  250. package/dist/services/connectors/zitadel.js.map +1 -1
  251. package/dist/services/domain/authentication.d.ts +43 -4
  252. package/dist/services/domain/authentication.d.ts.map +1 -1
  253. package/dist/services/domain/authentication.js +119 -40
  254. package/dist/services/domain/authentication.js.map +1 -1
  255. package/dist/services/domain/authorization.d.ts +11 -0
  256. package/dist/services/domain/authorization.d.ts.map +1 -1
  257. package/dist/services/domain/authorization.js +36 -1
  258. package/dist/services/domain/authorization.js.map +1 -1
  259. package/dist/services/domain/identity.d.ts +21 -9
  260. package/dist/services/domain/identity.d.ts.map +1 -1
  261. package/dist/services/domain/identity.js +187 -10
  262. package/dist/services/domain/identity.js.map +1 -1
  263. package/dist/services/domain/organization.d.ts +11 -10
  264. package/dist/services/domain/organization.d.ts.map +1 -1
  265. package/dist/services/domain/organization.js +48 -30
  266. package/dist/services/domain/organization.js.map +1 -1
  267. package/dist/services/emailVerification.d.ts +2 -2
  268. package/dist/services/enterpriseSso.d.ts +13 -6
  269. package/dist/services/enterpriseSso.d.ts.map +1 -1
  270. package/dist/services/enterpriseSso.js +75 -6
  271. package/dist/services/enterpriseSso.js.map +1 -1
  272. package/dist/services/events/subscribers/auditLog.js +1 -1
  273. package/dist/services/events/subscribers/auditLog.js.map +1 -1
  274. package/dist/services/events/types.d.ts +7 -1
  275. package/dist/services/events/types.d.ts.map +1 -1
  276. package/dist/services/events/types.js.map +1 -1
  277. package/dist/services/events/validate.d.ts.map +1 -1
  278. package/dist/services/events/validate.js +33 -0
  279. package/dist/services/events/validate.js.map +1 -1
  280. package/dist/services/features.d.ts.map +1 -1
  281. package/dist/services/features.js.map +1 -1
  282. package/dist/services/federation.d.ts +6 -1
  283. package/dist/services/federation.d.ts.map +1 -1
  284. package/dist/services/federation.js +31 -4
  285. package/dist/services/federation.js.map +1 -1
  286. package/dist/services/ipControls.js +2 -2
  287. package/dist/services/ipControls.js.map +1 -1
  288. package/dist/services/magicLinks.d.ts +2 -2
  289. package/dist/services/magicLinks.d.ts.map +1 -1
  290. package/dist/services/magicLinks.js +13 -9
  291. package/dist/services/magicLinks.js.map +1 -1
  292. package/dist/services/mfa.d.ts +53 -0
  293. package/dist/services/mfa.d.ts.map +1 -0
  294. package/dist/services/mfa.js +157 -0
  295. package/dist/services/mfa.js.map +1 -0
  296. package/dist/services/oauth2.d.ts +88 -14
  297. package/dist/services/oauth2.d.ts.map +1 -1
  298. package/dist/services/oauth2.js +125 -16
  299. package/dist/services/oauth2.js.map +1 -1
  300. package/dist/services/oidcSecretFormat.d.ts +3 -0
  301. package/dist/services/oidcSecretFormat.d.ts.map +1 -0
  302. package/dist/services/oidcSecretFormat.js +5 -0
  303. package/dist/services/oidcSecretFormat.js.map +1 -0
  304. package/dist/services/organizations.d.ts +4 -16
  305. package/dist/services/organizations.d.ts.map +1 -1
  306. package/dist/services/organizations.js +0 -62
  307. package/dist/services/organizations.js.map +1 -1
  308. package/dist/services/permissions.d.ts.map +1 -1
  309. package/dist/services/permissions.js +9 -1
  310. package/dist/services/permissions.js.map +1 -1
  311. package/dist/services/plugins/registry.d.ts.map +1 -1
  312. package/dist/services/plugins/registry.js.map +1 -1
  313. package/dist/services/plugins/types.d.ts.map +1 -1
  314. package/dist/services/queue/bullmq.d.ts.map +1 -1
  315. package/dist/services/queue/inProcess.d.ts.map +1 -1
  316. package/dist/services/redirectUri.d.ts +56 -0
  317. package/dist/services/redirectUri.d.ts.map +1 -0
  318. package/dist/services/redirectUri.js +129 -0
  319. package/dist/services/redirectUri.js.map +1 -0
  320. package/dist/services/redis.d.ts +1 -1
  321. package/dist/services/redis.d.ts.map +1 -1
  322. package/dist/services/scimCredentials.d.ts +46 -0
  323. package/dist/services/scimCredentials.d.ts.map +1 -0
  324. package/dist/services/scimCredentials.js +123 -0
  325. package/dist/services/scimCredentials.js.map +1 -0
  326. package/dist/services/scimLegacyMigration.d.ts +12 -0
  327. package/dist/services/scimLegacyMigration.d.ts.map +1 -0
  328. package/dist/services/scimLegacyMigration.js +44 -0
  329. package/dist/services/scimLegacyMigration.js.map +1 -0
  330. package/dist/services/secrets/awsKms.d.ts +2 -2
  331. package/dist/services/secrets/awsKms.d.ts.map +1 -1
  332. package/dist/services/secrets/awsKms.js +3 -5
  333. package/dist/services/secrets/awsKms.js.map +1 -1
  334. package/dist/services/secrets/azureKeyVault.d.ts.map +1 -1
  335. package/dist/services/secrets/database.d.ts.map +1 -1
  336. package/dist/services/secrets/database.js.map +1 -1
  337. package/dist/services/secrets/environment.d.ts.map +1 -1
  338. package/dist/services/secrets/environment.js.map +1 -1
  339. package/dist/services/secrets/index.d.ts.map +1 -1
  340. package/dist/services/secrets/password.d.ts.map +1 -1
  341. package/dist/services/secrets/password.js +0 -4
  342. package/dist/services/secrets/password.js.map +1 -1
  343. package/dist/services/secrets/provider.d.ts +2 -3
  344. package/dist/services/secrets/provider.d.ts.map +1 -1
  345. package/dist/services/secrets/vault.d.ts.map +1 -1
  346. package/dist/services/serviceAccounts.d.ts +20 -0
  347. package/dist/services/serviceAccounts.d.ts.map +1 -1
  348. package/dist/services/serviceAccounts.js +47 -1
  349. package/dist/services/serviceAccounts.js.map +1 -1
  350. package/dist/services/sessionRevocation.d.ts +76 -0
  351. package/dist/services/sessionRevocation.d.ts.map +1 -0
  352. package/dist/services/sessionRevocation.js +86 -0
  353. package/dist/services/sessionRevocation.js.map +1 -0
  354. package/dist/services/setup/configWriter.d.ts.map +1 -1
  355. package/dist/services/setup/configWriter.js.map +1 -1
  356. package/dist/services/singleUse.d.ts +68 -0
  357. package/dist/services/singleUse.d.ts.map +1 -0
  358. package/dist/services/singleUse.js +54 -0
  359. package/dist/services/singleUse.js.map +1 -0
  360. package/dist/services/smsOtp.d.ts.map +1 -1
  361. package/dist/services/smsOtp.js +12 -8
  362. package/dist/services/smsOtp.js.map +1 -1
  363. package/dist/services/ssoEndpointPolicy.d.ts +8 -0
  364. package/dist/services/ssoEndpointPolicy.d.ts.map +1 -0
  365. package/dist/services/ssoEndpointPolicy.js +136 -0
  366. package/dist/services/ssoEndpointPolicy.js.map +1 -0
  367. package/dist/services/stepUp.d.ts +35 -0
  368. package/dist/services/stepUp.d.ts.map +1 -0
  369. package/dist/services/stepUp.js +65 -0
  370. package/dist/services/stepUp.js.map +1 -0
  371. package/dist/services/tokens.d.ts +39 -11
  372. package/dist/services/tokens.d.ts.map +1 -1
  373. package/dist/services/tokens.js +80 -14
  374. package/dist/services/tokens.js.map +1 -1
  375. package/dist/services/totp.d.ts +46 -0
  376. package/dist/services/totp.d.ts.map +1 -1
  377. package/dist/services/totp.js +178 -41
  378. package/dist/services/totp.js.map +1 -1
  379. package/dist/services/trustedProxies.d.ts +90 -0
  380. package/dist/services/trustedProxies.d.ts.map +1 -0
  381. package/dist/services/trustedProxies.js +283 -0
  382. package/dist/services/trustedProxies.js.map +1 -0
  383. package/dist/services/users.d.ts +20 -12
  384. package/dist/services/users.d.ts.map +1 -1
  385. package/dist/services/users.js +24 -51
  386. package/dist/services/users.js.map +1 -1
  387. package/dist/services/webauthn.d.ts +8 -4
  388. package/dist/services/webauthn.d.ts.map +1 -1
  389. package/dist/services/webauthn.js +4 -4
  390. package/dist/services/webauthn.js.map +1 -1
  391. package/dist/services/webhooks.d.ts +20 -20
  392. package/dist/services/workflows/engine.d.ts +4 -2
  393. package/dist/services/workflows/engine.d.ts.map +1 -1
  394. package/dist/services/workflows/engine.js +181 -12
  395. package/dist/services/workflows/engine.js.map +1 -1
  396. package/dist/services/workflows/steps.d.ts +2 -0
  397. package/dist/services/workflows/steps.d.ts.map +1 -1
  398. package/dist/services/workflows/steps.js +8 -75
  399. package/dist/services/workflows/steps.js.map +1 -1
  400. package/dist/setup-server.js +2 -1
  401. package/dist/setup-server.js.map +1 -1
  402. package/dist/types.d.ts +33 -4
  403. package/dist/types.d.ts.map +1 -1
  404. package/dist/types.js +26 -2
  405. package/dist/types.js.map +1 -1
  406. package/package.json +25 -3
  407. package/dist/tests/errors.test.d.ts +0 -2
  408. package/dist/tests/errors.test.d.ts.map +0 -1
  409. package/dist/tests/errors.test.js +0 -64
  410. package/dist/tests/errors.test.js.map +0 -1
  411. package/dist/tests/events.test.d.ts +0 -2
  412. package/dist/tests/events.test.d.ts.map +0 -1
  413. package/dist/tests/events.test.js +0 -45
  414. package/dist/tests/events.test.js.map +0 -1
  415. package/dist/tests/featureFlags.test.d.ts +0 -2
  416. package/dist/tests/featureFlags.test.d.ts.map +0 -1
  417. package/dist/tests/featureFlags.test.js +0 -24
  418. package/dist/tests/featureFlags.test.js.map +0 -1
  419. package/dist/tests/integration/queue.test.d.ts +0 -2
  420. package/dist/tests/integration/queue.test.d.ts.map +0 -1
  421. package/dist/tests/integration/queue.test.js +0 -49
  422. package/dist/tests/integration/queue.test.js.map +0 -1
  423. package/dist/tests/plugins.test.d.ts +0 -2
  424. package/dist/tests/plugins.test.d.ts.map +0 -1
  425. package/dist/tests/plugins.test.js +0 -56
  426. package/dist/tests/plugins.test.js.map +0 -1
  427. package/dist/tests/result.test.d.ts +0 -2
  428. package/dist/tests/result.test.d.ts.map +0 -1
  429. package/dist/tests/result.test.js +0 -46
  430. package/dist/tests/result.test.js.map +0 -1
  431. package/dist/tests/setup/configWriter.test.d.ts +0 -2
  432. package/dist/tests/setup/configWriter.test.d.ts.map +0 -1
  433. package/dist/tests/setup/configWriter.test.js +0 -55
  434. package/dist/tests/setup/configWriter.test.js.map +0 -1
  435. package/dist/tests/setup/validation.test.d.ts +0 -2
  436. package/dist/tests/setup/validation.test.d.ts.map +0 -1
  437. package/dist/tests/setup/validation.test.js +0 -26
  438. package/dist/tests/setup/validation.test.js.map +0 -1
  439. package/dist/tests/smoke.test.d.ts +0 -2
  440. package/dist/tests/smoke.test.d.ts.map +0 -1
  441. package/dist/tests/smoke.test.js +0 -124
  442. package/dist/tests/smoke.test.js.map +0 -1
  443. package/src/cli.ts +0 -172
  444. package/src/config.ts +0 -143
  445. package/src/container.ts +0 -48
  446. package/src/db/index.ts +0 -53
  447. package/src/db/migrations/0000_skinny_ben_parker.sql +0 -553
  448. package/src/db/migrations/0001_brief_joseph.sql +0 -10
  449. package/src/db/migrations/0002_add_account_lockout.sql +0 -3
  450. package/src/db/migrations/0003_steep_rachel_grey.sql +0 -1
  451. package/src/db/migrations/0004_clever_bill_hollister.sql +0 -20
  452. package/src/db/migrations/0005_steep_the_call.sql +0 -2
  453. package/src/db/migrations/0006_ambitious_boomer.sql +0 -17
  454. package/src/db/migrations/0007_greedy_vindicator.sql +0 -40
  455. package/src/db/migrations/meta/0000_snapshot.json +0 -2964
  456. package/src/db/migrations/meta/0001_snapshot.json +0 -3031
  457. package/src/db/migrations/meta/0003_snapshot.json +0 -3051
  458. package/src/db/migrations/meta/_journal.json +0 -62
  459. package/src/db/schema.ts +0 -676
  460. package/src/db/seed.ts +0 -146
  461. package/src/di.ts +0 -81
  462. package/src/index.ts +0 -326
  463. package/src/lib/errors.ts +0 -139
  464. package/src/lib/result.ts +0 -44
  465. package/src/lib/webhookSignature.ts +0 -41
  466. package/src/plugins/appContext.ts +0 -76
  467. package/src/plugins/audit.ts +0 -42
  468. package/src/plugins/auth.ts +0 -230
  469. package/src/plugins/metrics.ts +0 -41
  470. package/src/plugins/mtls.ts +0 -94
  471. package/src/plugins/permissions.ts +0 -29
  472. package/src/plugins/rateLimit.ts +0 -133
  473. package/src/plugins/requestLogger.ts +0 -25
  474. package/src/plugins/tracing.ts +0 -22
  475. package/src/repositories/apiKey.ts +0 -158
  476. package/src/repositories/application.ts +0 -70
  477. package/src/repositories/audit.ts +0 -32
  478. package/src/repositories/index.ts +0 -9
  479. package/src/repositories/oidcConnection.ts +0 -111
  480. package/src/repositories/organization.ts +0 -167
  481. package/src/repositories/permission.ts +0 -153
  482. package/src/repositories/samlConnection.ts +0 -96
  483. package/src/repositories/session.ts +0 -86
  484. package/src/repositories/types.ts +0 -134
  485. package/src/repositories/user.ts +0 -161
  486. package/src/routes/admin/billing.ts +0 -48
  487. package/src/routes/admin/helpers.ts +0 -50
  488. package/src/routes/admin/index.ts +0 -16
  489. package/src/routes/admin/organizations.ts +0 -299
  490. package/src/routes/admin/permissions.ts +0 -80
  491. package/src/routes/admin/platform.ts +0 -335
  492. package/src/routes/admin/sso.ts +0 -138
  493. package/src/routes/admin/webhooks.ts +0 -73
  494. package/src/routes/admin.ts +0 -1
  495. package/src/routes/apiKeys.ts +0 -60
  496. package/src/routes/auth.ts +0 -214
  497. package/src/routes/authz.ts +0 -38
  498. package/src/routes/config.ts +0 -67
  499. package/src/routes/emailVerification.ts +0 -73
  500. package/src/routes/federation.ts +0 -156
  501. package/src/routes/helpers.ts +0 -17
  502. package/src/routes/magicLinks.ts +0 -107
  503. package/src/routes/oauth.ts +0 -167
  504. package/src/routes/oauth2.ts +0 -284
  505. package/src/routes/oidcEnterprise.ts +0 -166
  506. package/src/routes/password.ts +0 -90
  507. package/src/routes/profile.ts +0 -44
  508. package/src/routes/saml.ts +0 -209
  509. package/src/routes/scim.ts +0 -199
  510. package/src/routes/sdk.ts +0 -141
  511. package/src/routes/serviceAccounts.ts +0 -124
  512. package/src/routes/sessions.ts +0 -62
  513. package/src/routes/setup.ts +0 -315
  514. package/src/routes/smsOtp.ts +0 -67
  515. package/src/routes/totp.ts +0 -122
  516. package/src/routes/webauthn.ts +0 -147
  517. package/src/routes/workflows.ts +0 -157
  518. package/src/sdk/index.ts +0 -152
  519. package/src/sdk/types.ts +0 -54
  520. package/src/services/anomalyDetection.ts +0 -73
  521. package/src/services/application/authentication.ts +0 -75
  522. package/src/services/application/identity.ts +0 -56
  523. package/src/services/application/index.ts +0 -3
  524. package/src/services/application/organization.ts +0 -77
  525. package/src/services/applications.ts +0 -89
  526. package/src/services/audit.ts +0 -41
  527. package/src/services/auditExport.ts +0 -59
  528. package/src/services/billing.ts +0 -87
  529. package/src/services/cache.ts +0 -131
  530. package/src/services/configuration/profiles.ts +0 -115
  531. package/src/services/configuration.ts +0 -120
  532. package/src/services/connectors/google.ts +0 -92
  533. package/src/services/connectors/oidc.ts +0 -111
  534. package/src/services/connectors/registry.ts +0 -124
  535. package/src/services/connectors/types.ts +0 -38
  536. package/src/services/connectors/zitadel.ts +0 -77
  537. package/src/services/devices.ts +0 -76
  538. package/src/services/domain/authentication.ts +0 -279
  539. package/src/services/domain/authorization.ts +0 -49
  540. package/src/services/domain/identity.ts +0 -108
  541. package/src/services/domain/index.ts +0 -4
  542. package/src/services/domain/organization.ts +0 -114
  543. package/src/services/email.ts +0 -167
  544. package/src/services/emailVerification.ts +0 -75
  545. package/src/services/enterpriseSso.ts +0 -58
  546. package/src/services/events/bus.ts +0 -43
  547. package/src/services/events/subscribers/anomaly.ts +0 -13
  548. package/src/services/events/subscribers/auditLog.ts +0 -21
  549. package/src/services/events/subscribers/webhook.ts +0 -39
  550. package/src/services/events/subscribers/webhookDispatch.ts +0 -14
  551. package/src/services/events/types.ts +0 -106
  552. package/src/services/events/validate.ts +0 -118
  553. package/src/services/featureFlags.ts +0 -90
  554. package/src/services/features.ts +0 -22
  555. package/src/services/federation.ts +0 -30
  556. package/src/services/hibp.ts +0 -28
  557. package/src/services/ipControls.ts +0 -99
  558. package/src/services/magicLinks.ts +0 -51
  559. package/src/services/oauth2.ts +0 -216
  560. package/src/services/organizations.ts +0 -171
  561. package/src/services/permissions.ts +0 -146
  562. package/src/services/plugins/registry.ts +0 -242
  563. package/src/services/plugins/types.ts +0 -98
  564. package/src/services/queue/bullmq.ts +0 -104
  565. package/src/services/queue/inProcess.ts +0 -75
  566. package/src/services/queue/index.ts +0 -19
  567. package/src/services/queue/types.ts +0 -26
  568. package/src/services/redis.ts +0 -16
  569. package/src/services/secrets/awsKms.ts +0 -97
  570. package/src/services/secrets/azureKeyVault.ts +0 -171
  571. package/src/services/secrets/database.ts +0 -166
  572. package/src/services/secrets/environment.ts +0 -117
  573. package/src/services/secrets/index.ts +0 -50
  574. package/src/services/secrets/password.ts +0 -73
  575. package/src/services/secrets/provider.ts +0 -36
  576. package/src/services/secrets/vault.ts +0 -149
  577. package/src/services/secrets.ts +0 -2
  578. package/src/services/serviceAccounts.ts +0 -74
  579. package/src/services/setup/configWriter.ts +0 -200
  580. package/src/services/setup/diagnostics.ts +0 -76
  581. package/src/services/setup/token.ts +0 -42
  582. package/src/services/setup/types.ts +0 -40
  583. package/src/services/setup/validation.ts +0 -205
  584. package/src/services/sms.ts +0 -81
  585. package/src/services/smsOtp.ts +0 -74
  586. package/src/services/tokens.ts +0 -287
  587. package/src/services/totp.ts +0 -113
  588. package/src/services/users.ts +0 -239
  589. package/src/services/webauthn.ts +0 -193
  590. package/src/services/webhooks.ts +0 -190
  591. package/src/services/workflows/engine.ts +0 -125
  592. package/src/services/workflows/steps.ts +0 -129
  593. package/src/services/zitadel.ts +0 -277
  594. package/src/setup-server.ts +0 -71
  595. package/src/tests/errors.test.ts +0 -74
  596. package/src/tests/events.test.ts +0 -52
  597. package/src/tests/featureFlags.test.ts +0 -26
  598. package/src/tests/integration/queue.test.ts +0 -54
  599. package/src/tests/plugins.test.ts +0 -73
  600. package/src/tests/result.test.ts +0 -52
  601. package/src/tests/setup/configWriter.test.ts +0 -69
  602. package/src/tests/setup/validation.test.ts +0 -29
  603. package/src/tests/smoke.test.ts +0 -136
  604. package/src/types.ts +0 -70
@@ -1,120 +0,0 @@
1
- import { config as rawConfig } from "../config.js";
2
-
3
- export interface RuntimeConfiguration {
4
- nodeEnv: string;
5
- port: number;
6
- host: string;
7
- databaseUrl: string;
8
- redisUrl: string;
9
- publicUrl?: string;
10
- cookieDomain?: string;
11
- cookieSecure: boolean;
12
- internalApiKey?: string;
13
- accessTokenTtlSeconds: number;
14
- refreshTokenTtlSeconds: number;
15
- secretsProvider: "database" | "environment";
16
- queueProvider: "in-process" | "bullmq";
17
- hibpCheckEnabled: boolean;
18
- magicLinkTtlSeconds: number;
19
- oauthCodeTtlSeconds: number;
20
- totpIssuer: string;
21
- emailProvider: string;
22
- smsProvider: string;
23
- auditWebhookUrl?: string;
24
- auditConsoleExport: boolean;
25
- featureFlags: Record<string, boolean>;
26
- plugins: string[];
27
- allowedOrigins: string[];
28
- zitadel?: {
29
- domain?: string;
30
- orgId?: string;
31
- projectId?: string;
32
- serviceClientId?: string;
33
- serviceClientSecret?: string;
34
- servicePat?: string;
35
- clientId?: string;
36
- clientSecret?: string;
37
- googleIdpId?: string;
38
- githubIdpId?: string;
39
- };
40
- }
41
-
42
- export class ConfigurationService {
43
- private readonly values: RuntimeConfiguration;
44
-
45
- constructor(overrides: Partial<RuntimeConfiguration> = {}) {
46
- this.values = this.load(overrides);
47
- }
48
-
49
- private load(overrides: Partial<RuntimeConfiguration>): RuntimeConfiguration {
50
- const featureFlags = this.parseFeatureFlags(process.env.KEYSTONE_FEATURE_FLAGS);
51
-
52
- return {
53
- nodeEnv: rawConfig.NODE_ENV,
54
- port: rawConfig.PORT,
55
- host: rawConfig.HOST,
56
- databaseUrl: rawConfig.DATABASE_URL,
57
- redisUrl: rawConfig.REDIS_URL,
58
- publicUrl: rawConfig.AUTH_API_PUBLIC_URL,
59
- cookieDomain: rawConfig.COOKIE_DOMAIN,
60
- cookieSecure: rawConfig.COOKIE_SECURE,
61
- internalApiKey: rawConfig.INTERNAL_API_KEY,
62
- accessTokenTtlSeconds: rawConfig.ACCESS_TOKEN_TTL_SECONDS,
63
- refreshTokenTtlSeconds: rawConfig.REFRESH_TOKEN_TTL_SECONDS,
64
- secretsProvider: rawConfig.KEYSTONE_SECRETS_PROVIDER as RuntimeConfiguration["secretsProvider"],
65
- queueProvider: rawConfig.KEYSTONE_QUEUE_PROVIDER as RuntimeConfiguration["queueProvider"],
66
- hibpCheckEnabled: rawConfig.HIBP_CHECK_ENABLED,
67
- magicLinkTtlSeconds: rawConfig.MAGIC_LINK_TTL_SECONDS,
68
- oauthCodeTtlSeconds: rawConfig.OAUTH_CODE_TTL_SECONDS,
69
- totpIssuer: rawConfig.TOTP_ISSUER,
70
- emailProvider: rawConfig.EMAIL_PROVIDER,
71
- smsProvider: rawConfig.SMS_PROVIDER,
72
- auditWebhookUrl: rawConfig.AUDIT_WEBHOOK_URL,
73
- auditConsoleExport: rawConfig.AUDIT_CONSOLE_EXPORT === "true",
74
- featureFlags: { ...featureFlags, ...overrides.featureFlags },
75
- plugins: (rawConfig.KEYSTONE_PLUGINS || "").split(",").map((s) => s.trim()).filter(Boolean),
76
- allowedOrigins: rawConfig.ALLOWED_ORIGINS,
77
- zitadel: {
78
- domain: rawConfig.ZITADEL_DOMAIN,
79
- orgId: rawConfig.ZITADEL_ORG_ID,
80
- projectId: rawConfig.ZITADEL_PROJECT_ID,
81
- serviceClientId: rawConfig.ZITADEL_SERVICE_CLIENT_ID,
82
- serviceClientSecret: rawConfig.ZITADEL_SERVICE_CLIENT_SECRET,
83
- servicePat: rawConfig.ZITADEL_SERVICE_PAT,
84
- clientId: rawConfig.ZITADEL_CLIENT_ID,
85
- clientSecret: rawConfig.ZITADEL_CLIENT_SECRET,
86
- googleIdpId: rawConfig.ZITADEL_GOOGLE_IDP_ID,
87
- githubIdpId: rawConfig.ZITADEL_GITHUB_IDP_ID,
88
- },
89
- ...overrides,
90
- };
91
- }
92
-
93
- private parseFeatureFlags(value?: string): Record<string, boolean> {
94
- if (!value) return {};
95
- const flags: Record<string, boolean> = {};
96
- for (const part of value.split(",")) {
97
- const [key, val] = part.trim().split("=");
98
- if (key) flags[key] = val === "true" || val === "1";
99
- }
100
- return flags;
101
- }
102
-
103
- get(): RuntimeConfiguration {
104
- return this.values;
105
- }
106
-
107
- getValue<K extends keyof RuntimeConfiguration>(key: K): RuntimeConfiguration[K] {
108
- return this.values[key];
109
- }
110
-
111
- isEnabled(flag: string): boolean {
112
- return this.values.featureFlags[flag] === true;
113
- }
114
-
115
- isProduction(): boolean {
116
- return this.values.nodeEnv === "production";
117
- }
118
- }
119
-
120
- export const configurationService = new ConfigurationService();
@@ -1,92 +0,0 @@
1
- import { OidcConnector, normalizePayload } from "./oidc.js";
2
- import type { ExternalIdentity, AuthorizeUrlOptions } from "./types.js";
3
-
4
- /**
5
- * Google-specific OIDC connector.
6
- *
7
- * Extends the generic OIDC connector with Google-specific authorization
8
- * parameters and a userinfo fallback. Google returns most claims in the
9
- * id_token, but the userinfo endpoint is used as a fallback when claims
10
- * are missing.
11
- */
12
- export class GoogleConnector extends OidcConnector {
13
- getAuthorizeUrl(opts: AuthorizeUrlOptions): string {
14
- // Ask the user to pick an account every time. This avoids silent
15
- // logins with the wrong Google account when multiple accounts exist.
16
- opts.extraParams = {
17
- ...opts.extraParams,
18
- prompt: "select_account",
19
- access_type: "online",
20
- };
21
- return super.getAuthorizeUrl(opts);
22
- }
23
-
24
- async exchangeCode(code: string, redirectUri: string): Promise<ExternalIdentity> {
25
- const identity = await super.exchangeCode(code, redirectUri);
26
-
27
- // Google usually returns picture, email_verified, etc. in the id_token.
28
- // If something is missing, enrich from the userinfo endpoint.
29
- if (!identity.name || !identity.picture || identity.emailVerified === undefined) {
30
- try {
31
- const enriched = await this.fetchUserinfo(code, redirectUri);
32
- return {
33
- ...identity,
34
- name: identity.name || enriched.name,
35
- picture: identity.picture || enriched.picture,
36
- emailVerified: identity.emailVerified ?? enriched.emailVerified,
37
- };
38
- } catch (err) {
39
- // Userinfo enrichment is best-effort; the id_token identity is still valid.
40
- this.logDebug("Google userinfo enrichment failed", err);
41
- }
42
- }
43
-
44
- return identity;
45
- }
46
-
47
- private async fetchUserinfo(code: string, redirectUri: string): Promise<ExternalIdentity> {
48
- // Re-exchange the code for an access token. In practice the parent
49
- // exchange already did this, but we do not retain the access token.
50
- // A future refactor could pass it through to avoid a second request.
51
- const params = new URLSearchParams({
52
- grant_type: "authorization_code",
53
- client_id: this.config.clientId,
54
- client_secret: this.config.clientSecret,
55
- code,
56
- redirect_uri: redirectUri,
57
- });
58
-
59
- const tokenRes = await fetch(this.config.tokenEndpoint!, {
60
- method: "POST",
61
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
62
- body: params.toString(),
63
- });
64
-
65
- if (!tokenRes.ok) {
66
- throw new Error(`Google token refresh for userinfo failed: ${tokenRes.status}`);
67
- }
68
-
69
- const tokenData = (await tokenRes.json()) as { access_token?: string };
70
- if (!tokenData.access_token) {
71
- throw new Error("Google did not return an access_token for userinfo");
72
- }
73
-
74
- const userinfoRes = await fetch(this.config.userinfoEndpoint!, {
75
- headers: { Authorization: `Bearer ${tokenData.access_token}` },
76
- });
77
-
78
- if (!userinfoRes.ok) {
79
- throw new Error(`Google userinfo request failed: ${userinfoRes.status}`);
80
- }
81
-
82
- const payload = (await userinfoRes.json()) as Record<string, unknown>;
83
- return normalizePayload(payload, this.config.attributeMapping);
84
- }
85
-
86
- private logDebug(message: string, err: unknown): void {
87
- if (process.env.NODE_ENV !== "test") {
88
- // eslint-disable-next-line no-console
89
- console.debug(`[GoogleConnector] ${message}:`, err);
90
- }
91
- }
92
- }
@@ -1,111 +0,0 @@
1
- import { createRemoteJWKSet, jwtVerify } from "jose";
2
- import type { IdentityConnector, ExternalIdentity, AuthorizeUrlOptions, ConnectorConfig } from "./types.js";
3
- import { cache } from "../cache.js";
4
-
5
- export class OidcConnector implements IdentityConnector {
6
- id: string;
7
- name: string;
8
- type: string;
9
- protected config: ConnectorConfig;
10
-
11
- constructor(id: string, name: string, type: string, config: ConnectorConfig) {
12
- this.id = id;
13
- this.name = name;
14
- this.type = type;
15
- this.config = config;
16
- }
17
-
18
- getAuthorizeUrl(opts: AuthorizeUrlOptions): string {
19
- const scopes = opts.scopes ?? this.config.scopes ?? ["openid", "profile", "email"];
20
- const params = new URLSearchParams({
21
- client_id: this.config.clientId,
22
- redirect_uri: opts.redirectUri,
23
- response_type: "code",
24
- scope: scopes.join(" "),
25
- state: opts.state,
26
- });
27
- if (this.config.idpHint) {
28
- params.set("idp_hint", this.config.idpHint);
29
- }
30
- if (opts.extraParams) {
31
- for (const [k, v] of Object.entries(opts.extraParams)) {
32
- params.set(k, v);
33
- }
34
- }
35
- return `${this.config.authorizationEndpoint}?${params.toString()}`;
36
- }
37
-
38
- async exchangeCode(code: string, redirectUri: string): Promise<ExternalIdentity> {
39
- const params = new URLSearchParams({
40
- grant_type: "authorization_code",
41
- client_id: this.config.clientId,
42
- client_secret: this.config.clientSecret,
43
- code,
44
- redirect_uri: redirectUri,
45
- });
46
-
47
- const res = await fetch(this.config.tokenEndpoint!, {
48
- method: "POST",
49
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
50
- body: params.toString(),
51
- });
52
-
53
- if (!res.ok) {
54
- const text = await res.text();
55
- throw new Error(`OIDC token exchange failed: ${res.status} ${text}`);
56
- }
57
-
58
- const data = (await res.json()) as { id_token: string; access_token?: string };
59
- if (!data.id_token) {
60
- throw new Error("OIDC provider did not return an id_token");
61
- }
62
- return this.verifyToken(data.id_token);
63
- }
64
-
65
- async verifyToken(token: string): Promise<ExternalIdentity> {
66
- const jwksUrl = this.config.jwksUri || ((await this.discovery())?.jwks_uri as string);
67
- if (!jwksUrl) {
68
- throw new Error("OIDC connector missing jwks_uri");
69
- }
70
- const JWKS = createRemoteJWKSet(new URL(jwksUrl));
71
- const { payload } = await jwtVerify(token, JWKS, {
72
- issuer: this.config.issuer,
73
- audience: this.config.clientId,
74
- });
75
- return normalizePayload(payload as Record<string, unknown>, this.config.attributeMapping);
76
- }
77
-
78
- private async discovery(): Promise<Record<string, unknown>> {
79
- if (!this.config.issuer) throw new Error("OIDC connector missing issuer for discovery");
80
- const key = `oidc:discovery:${this.config.issuer}`;
81
- const cached = await cache.get<Record<string, unknown>>(key);
82
- if (cached) return cached;
83
-
84
- const res = await fetch(`${this.config.issuer.replace(/\/$/, "")}/.well-known/openid-configuration`);
85
- if (!res.ok) throw new Error(`OIDC discovery failed: ${res.status}`);
86
- const data = (await res.json()) as Record<string, unknown>;
87
- await cache.set(key, data, 3600);
88
- return data;
89
- }
90
- }
91
-
92
- export function normalizePayload(
93
- payload: Record<string, unknown>,
94
- mapping?: Record<string, string>
95
- ): ExternalIdentity {
96
- const m = mapping ?? {};
97
- const get = (key: string): unknown => payload[m[key] || key];
98
- const email = String(get("email") || "");
99
- if (!email) {
100
- throw new Error("Identity provider did not return an email address");
101
- }
102
- return {
103
- sub: String(get("sub") || ""),
104
- email,
105
- emailVerified: get("email_verified") === true,
106
- name: get("name") ? String(get("name")) : undefined,
107
- picture: get("picture") ? String(get("picture")) : undefined,
108
- username: get("preferred_username") ? String(get("preferred_username")) : undefined,
109
- raw: payload,
110
- };
111
- }
@@ -1,124 +0,0 @@
1
- import { config, isZitadelConfigured } from "../../config.js";
2
- import { getConnectorFactory } from "../plugins/registry.js";
3
- import type { IdentityConnector, ConnectorConfig } from "./types.js";
4
- import { OidcConnector } from "./oidc.js";
5
- import { GoogleConnector } from "./google.js";
6
- import { ZitadelConnector } from "./zitadel.js";
7
-
8
- const wellKnownIssuers: Record<string, { issuer: string; authorizationEndpoint?: string; tokenEndpoint?: string; userinfoEndpoint?: string; jwksUri?: string }> = {
9
- google: {
10
- issuer: "https://accounts.google.com",
11
- authorizationEndpoint: "https://accounts.google.com/o/oauth2/v2/auth",
12
- tokenEndpoint: "https://oauth2.googleapis.com/token",
13
- userinfoEndpoint: "https://openidconnect.googleapis.com/v1/userinfo",
14
- jwksUri: "https://www.googleapis.com/oauth2/v3/certs",
15
- },
16
- github: {
17
- issuer: "https://github.com",
18
- authorizationEndpoint: "https://github.com/login/oauth/authorize",
19
- tokenEndpoint: "https://github.com/login/oauth/access_token",
20
- userinfoEndpoint: "https://api.github.com/user",
21
- },
22
- azure: {
23
- issuer: "https://login.microsoftonline.com/common/v2.0",
24
- authorizationEndpoint: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
25
- tokenEndpoint: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
26
- userinfoEndpoint: "https://graph.microsoft.com/oidc/userinfo",
27
- jwksUri: "https://login.microsoftonline.com/common/discovery/v2.0/keys",
28
- },
29
- okta: {
30
- issuer: process.env.OKTA_ISSUER || "",
31
- authorizationEndpoint: process.env.OKTA_AUTHORIZATION_ENDPOINT || "",
32
- tokenEndpoint: process.env.OKTA_TOKEN_ENDPOINT || "",
33
- userinfoEndpoint: process.env.OKTA_USERINFO_ENDPOINT || "",
34
- jwksUri: process.env.OKTA_JWKS_URI || "",
35
- },
36
- keycloak: {
37
- issuer: process.env.KEYCLOAK_ISSUER || "",
38
- authorizationEndpoint: process.env.KEYCLOAK_AUTHORIZATION_ENDPOINT || "",
39
- tokenEndpoint: process.env.KEYCLOAK_TOKEN_ENDPOINT || "",
40
- userinfoEndpoint: process.env.KEYCLOAK_USERINFO_ENDPOINT || "",
41
- jwksUri: process.env.KEYCLOAK_JWKS_URI || "",
42
- },
43
- };
44
-
45
- function getProviderEnvPrefix(type: string): string {
46
- return type.toUpperCase();
47
- }
48
-
49
- export function buildConnector(type: string, overrides?: Partial<ConnectorConfig>): IdentityConnector {
50
- const pluginFactory = getConnectorFactory(type);
51
- if (pluginFactory) {
52
- return pluginFactory(overrides);
53
- }
54
-
55
- if (type === "zitadel") {
56
- if (!isZitadelConfigured()) {
57
- throw new Error("Zitadel connector is not configured. Set ZITADEL_DOMAIN and ZITADEL_CLIENT_ID.");
58
- }
59
- return new ZitadelConnector({
60
- issuer: config.ZITADEL_DOMAIN,
61
- clientId: config.ZITADEL_CLIENT_ID!,
62
- clientSecret: config.ZITADEL_CLIENT_SECRET || "",
63
- scopes: ["openid", "profile", "email"],
64
- ...overrides,
65
- });
66
- }
67
-
68
- const prefix = getProviderEnvPrefix(type);
69
- const envClientId = process.env[`${prefix}_CLIENT_ID`] || "";
70
- const envClientSecret = process.env[`${prefix}_CLIENT_SECRET`] || "";
71
- const envIssuer = process.env[`${prefix}_ISSUER`] || "";
72
-
73
- const wellKnown = wellKnownIssuers[type];
74
- if (!wellKnown && !envIssuer) {
75
- throw new Error(`${type} connector is not configured. Set ${prefix}_ISSUER, ${prefix}_CLIENT_ID, and ${prefix}_CLIENT_SECRET.`);
76
- }
77
-
78
- const cfg: ConnectorConfig = {
79
- issuer: envIssuer || wellKnown?.issuer,
80
- authorizationEndpoint: process.env[`${prefix}_AUTHORIZATION_ENDPOINT`] || wellKnown?.authorizationEndpoint,
81
- tokenEndpoint: process.env[`${prefix}_TOKEN_ENDPOINT`] || wellKnown?.tokenEndpoint,
82
- userinfoEndpoint: process.env[`${prefix}_USERINFO_ENDPOINT`] || wellKnown?.userinfoEndpoint,
83
- jwksUri: process.env[`${prefix}_JWKS_URI`] || wellKnown?.jwksUri,
84
- clientId: envClientId || overrides?.clientId || "",
85
- clientSecret: envClientSecret || overrides?.clientSecret || "",
86
- scopes: ["openid", "profile", "email"],
87
- ...overrides,
88
- };
89
-
90
- if (!cfg.clientId || !cfg.clientSecret || !cfg.issuer) {
91
- throw new Error(`${type} connector is not fully configured. Set ${prefix}_CLIENT_ID, ${prefix}_CLIENT_SECRET, and ${prefix}_ISSUER.`);
92
- }
93
-
94
- if (type === "google") {
95
- return new GoogleConnector(type, type, type, cfg);
96
- }
97
-
98
- return new OidcConnector(type, type, type, cfg);
99
- }
100
-
101
- export function listSupportedProviders(): string[] {
102
- return ["zitadel", "google", "github", "azure", "okta", "keycloak"];
103
- }
104
-
105
- /**
106
- * Returns supported providers annotated with whether they are currently
107
- * configured with client credentials in the environment.
108
- */
109
- export function listConfiguredProviders(): Array<{ type: string; name: string; configured: boolean }> {
110
- return listSupportedProviders().map((type) => {
111
- const prefix = type.toUpperCase();
112
- let configured = false;
113
-
114
- if (type === "zitadel") {
115
- configured = Boolean(process.env.ZITADEL_DOMAIN && process.env.ZITADEL_CLIENT_ID);
116
- } else {
117
- configured = Boolean(
118
- process.env[`${prefix}_CLIENT_ID`] && process.env[`${prefix}_CLIENT_SECRET`]
119
- );
120
- }
121
-
122
- return { type, name: type.charAt(0).toUpperCase() + type.slice(1), configured };
123
- });
124
- }
@@ -1,38 +0,0 @@
1
- export interface ExternalIdentity {
2
- sub: string;
3
- email: string;
4
- emailVerified?: boolean;
5
- name?: string;
6
- picture?: string;
7
- username?: string;
8
- raw?: Record<string, unknown>;
9
- }
10
-
11
- export interface AuthorizeUrlOptions {
12
- state: string;
13
- redirectUri: string;
14
- scopes?: string[];
15
- extraParams?: Record<string, string>;
16
- }
17
-
18
- export interface IdentityConnector {
19
- id: string;
20
- name: string;
21
- type: string;
22
- getAuthorizeUrl(opts: AuthorizeUrlOptions): string | Promise<string>;
23
- exchangeCode(code: string, redirectUri: string): Promise<ExternalIdentity>;
24
- verifyToken?(token: string): Promise<ExternalIdentity>;
25
- }
26
-
27
- export interface ConnectorConfig {
28
- issuer?: string;
29
- authorizationEndpoint?: string;
30
- tokenEndpoint?: string;
31
- userinfoEndpoint?: string;
32
- jwksUri?: string;
33
- clientId: string;
34
- clientSecret: string;
35
- scopes?: string[];
36
- idpHint?: string;
37
- attributeMapping?: Record<string, string>;
38
- }
@@ -1,77 +0,0 @@
1
- import { createRemoteJWKSet, jwtVerify } from "jose";
2
- import { config, zitadelBaseUrl } from "../../config.js";
3
- import type { IdentityConnector, ExternalIdentity, AuthorizeUrlOptions, ConnectorConfig } from "./types.js";
4
- import { normalizePayload } from "./oidc.js";
5
-
6
- export class ZitadelConnector implements IdentityConnector {
7
- id = "zitadel";
8
- name = "Zitadel";
9
- type = "zitadel";
10
- private cfg: ConnectorConfig;
11
- private cachedJwksUrl: string | null = null;
12
-
13
- constructor(cfg: ConnectorConfig) {
14
- this.cfg = cfg;
15
- }
16
-
17
- getAuthorizeUrl(opts: AuthorizeUrlOptions): string {
18
- const redirectUri = opts.redirectUri;
19
- const params = new URLSearchParams({
20
- client_id: this.cfg.clientId,
21
- redirect_uri: redirectUri,
22
- response_type: "code",
23
- scope: (opts.scopes ?? ["openid", "profile", "email"]).join(" "),
24
- state: opts.state,
25
- });
26
- if (this.cfg.idpHint) {
27
- params.set("idp_hint", this.cfg.idpHint);
28
- }
29
- return `${zitadelBaseUrl()}/oauth/v2/authorize?${params.toString()}`;
30
- }
31
-
32
- async exchangeCode(code: string, redirectUri: string): Promise<ExternalIdentity> {
33
- const params = new URLSearchParams({
34
- grant_type: "authorization_code",
35
- client_id: this.cfg.clientId,
36
- client_secret: this.cfg.clientSecret,
37
- code,
38
- redirect_uri: redirectUri,
39
- });
40
-
41
- const res = await fetch(`${zitadelBaseUrl()}/oauth/v2/token`, {
42
- method: "POST",
43
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
44
- body: params.toString(),
45
- });
46
-
47
- if (!res.ok) {
48
- const text = await res.text();
49
- throw new Error(`Zitadel token exchange failed: ${res.status} ${text}`);
50
- }
51
-
52
- const data = (await res.json()) as { id_token: string };
53
- return this.verifyToken(data.id_token);
54
- }
55
-
56
- async verifyToken(token: string): Promise<ExternalIdentity> {
57
- const jwksUrl = await this.getJwksUrl();
58
- const JWKS = createRemoteJWKSet(new URL(jwksUrl));
59
- const issuer = config.ZITADEL_DOMAIN!.startsWith("http")
60
- ? config.ZITADEL_DOMAIN!
61
- : `https://${config.ZITADEL_DOMAIN!}`;
62
- const { payload } = await jwtVerify(token, JWKS, {
63
- issuer,
64
- audience: this.cfg.clientId,
65
- });
66
- return normalizePayload(payload as Record<string, unknown>, this.cfg.attributeMapping);
67
- }
68
-
69
- private async getJwksUrl(): Promise<string> {
70
- if (this.cachedJwksUrl) return this.cachedJwksUrl;
71
- const res = await fetch(`${zitadelBaseUrl()}/.well-known/openid-configuration`);
72
- if (!res.ok) throw new Error(`Zitadel discovery failed: ${res.status}`);
73
- const discovery = (await res.json()) as Record<string, unknown>;
74
- this.cachedJwksUrl = (discovery.jwks_uri as string) || `${zitadelBaseUrl()}/oauth/v2/keys`;
75
- return this.cachedJwksUrl;
76
- }
77
- }
@@ -1,76 +0,0 @@
1
- import crypto from "node:crypto";
2
- import type { FastifyRequest } from "fastify";
3
- import { eq, and } from "drizzle-orm";
4
- import { db } from "../db/index.js";
5
- import { userDevices, users } from "../db/schema.js";
6
- import { sendNewDeviceAlert } from "./email.js";
7
-
8
- export function fingerprintFromRequest(request: FastifyRequest): string {
9
- const ip = request.ip || "unknown";
10
- const userAgent = request.headers["user-agent"] || "unknown";
11
- const acceptLanguage = request.headers["accept-language"] || "unknown";
12
- const value = `${ip}:${userAgent}:${acceptLanguage}`;
13
- return crypto.createHash("sha256").update(value).digest("hex");
14
- }
15
-
16
- export async function recordDevice(
17
- userId: string,
18
- fingerprint: string,
19
- ip?: string,
20
- userAgent?: string
21
- ) {
22
- const now = new Date();
23
-
24
- const [existing] = await db
25
- .select({ id: userDevices.id })
26
- .from(userDevices)
27
- .where(
28
- and(
29
- eq(userDevices.userId, userId),
30
- eq(userDevices.fingerprintHash, fingerprint)
31
- )
32
- )
33
- .limit(1);
34
-
35
- if (existing) {
36
- await db
37
- .update(userDevices)
38
- .set({
39
- lastSeenAt: now,
40
- ipAddress: ip ?? null,
41
- userAgent: userAgent ?? null,
42
- })
43
- .where(eq(userDevices.id, existing.id));
44
- return existing.id;
45
- }
46
-
47
- const [record] = await db
48
- .insert(userDevices)
49
- .values({
50
- userId,
51
- fingerprintHash: fingerprint,
52
- ipAddress: ip ?? null,
53
- userAgent: userAgent ?? null,
54
- firstSeenAt: now,
55
- lastSeenAt: now,
56
- })
57
- .returning();
58
-
59
- // Send new-device alert asynchronously; do not block the login flow.
60
- const [user] = await db.select().from(users).where(eq(users.id, userId)).limit(1);
61
- if (user && !record.newDeviceAlertSent) {
62
- sendNewDeviceAlert({
63
- email: user.email,
64
- ipAddress: ip,
65
- userAgent: userAgent,
66
- }).catch((err: unknown) => {
67
- console.error("[devices] failed to send new-device alert:", err);
68
- });
69
- await db
70
- .update(userDevices)
71
- .set({ newDeviceAlertSent: true })
72
- .where(eq(userDevices.id, record.id));
73
- }
74
-
75
- return record.id;
76
- }