@hilbras/keystone 1.5.0 → 1.9.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 (559) hide show
  1. package/CHANGELOG.md +272 -0
  2. package/README.md +59 -25
  3. package/dist/cli.js +25 -27
  4. package/dist/cli.js.map +1 -1
  5. package/dist/config.d.ts +15 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +45 -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/{src/db/migrations/meta/0007_snapshot.json → dist/db/migrations/meta/0008_snapshot.json} +136 -32
  20. package/{src/db/migrations/meta/0006_snapshot.json → dist/db/migrations/meta/0009_snapshot.json} +359 -30
  21. package/{src/db/migrations/meta/0005_snapshot.json → dist/db/migrations/meta/0010_snapshot.json} +459 -29
  22. package/{src/db/migrations/meta/0004_snapshot.json → dist/db/migrations/meta/0011_snapshot.json} +594 -30
  23. package/dist/db/migrations/meta/0012_snapshot.json +3891 -0
  24. package/dist/db/migrations/meta/0013_snapshot.json +3919 -0
  25. package/dist/db/migrations/meta/0014_snapshot.json +4311 -0
  26. package/dist/db/migrations/meta/_journal.json +49 -0
  27. package/dist/db/reencryptOidcSecrets.d.ts +2 -0
  28. package/dist/db/reencryptOidcSecrets.d.ts.map +1 -0
  29. package/dist/db/reencryptOidcSecrets.js +41 -0
  30. package/dist/db/reencryptOidcSecrets.js.map +1 -0
  31. package/dist/db/schema.d.ts +2521 -53
  32. package/dist/db/schema.d.ts.map +1 -1
  33. package/dist/db/schema.js +118 -3
  34. package/dist/db/schema.js.map +1 -1
  35. package/dist/db/seed.js +67 -40
  36. package/dist/db/seed.js.map +1 -1
  37. package/dist/di.d.ts.map +1 -1
  38. package/dist/di.js +11 -3
  39. package/dist/di.js.map +1 -1
  40. package/dist/index.d.ts +2 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +26 -2
  43. package/dist/index.js.map +1 -1
  44. package/dist/lib/errors.d.ts +2 -1
  45. package/dist/lib/errors.d.ts.map +1 -1
  46. package/dist/lib/errors.js +10 -0
  47. package/dist/lib/errors.js.map +1 -1
  48. package/dist/plugins/appContext.d.ts.map +1 -1
  49. package/dist/plugins/appContext.js +3 -12
  50. package/dist/plugins/appContext.js.map +1 -1
  51. package/dist/plugins/audit.d.ts.map +1 -1
  52. package/dist/plugins/audit.js +26 -6
  53. package/dist/plugins/audit.js.map +1 -1
  54. package/dist/plugins/auth.d.ts.map +1 -1
  55. package/dist/plugins/auth.js +32 -7
  56. package/dist/plugins/auth.js.map +1 -1
  57. package/dist/plugins/metrics.d.ts.map +1 -1
  58. package/dist/plugins/mtls.d.ts.map +1 -1
  59. package/dist/plugins/permissions.d.ts.map +1 -1
  60. package/dist/plugins/permissions.js +29 -9
  61. package/dist/plugins/permissions.js.map +1 -1
  62. package/dist/plugins/rateLimit.d.ts +15 -0
  63. package/dist/plugins/rateLimit.d.ts.map +1 -1
  64. package/dist/plugins/rateLimit.js +11 -1
  65. package/dist/plugins/rateLimit.js.map +1 -1
  66. package/dist/plugins/requestLogger.d.ts.map +1 -1
  67. package/dist/repositories/apiKey.d.ts.map +1 -1
  68. package/dist/repositories/application.d.ts.map +1 -1
  69. package/dist/repositories/application.js +1 -1
  70. package/dist/repositories/application.js.map +1 -1
  71. package/dist/repositories/audit.d.ts.map +1 -1
  72. package/dist/repositories/index.d.ts +3 -0
  73. package/dist/repositories/index.d.ts.map +1 -1
  74. package/dist/repositories/index.js +3 -0
  75. package/dist/repositories/index.js.map +1 -1
  76. package/dist/repositories/mfaChallenge.d.ts +23 -0
  77. package/dist/repositories/mfaChallenge.d.ts.map +1 -0
  78. package/dist/repositories/mfaChallenge.js +71 -0
  79. package/dist/repositories/mfaChallenge.js.map +1 -0
  80. package/dist/repositories/oidcConnection.d.ts +27 -43
  81. package/dist/repositories/oidcConnection.d.ts.map +1 -1
  82. package/dist/repositories/oidcConnection.js +15 -6
  83. package/dist/repositories/oidcConnection.js.map +1 -1
  84. package/dist/repositories/organization.d.ts +9 -9
  85. package/dist/repositories/organization.d.ts.map +1 -1
  86. package/dist/repositories/organization.js +91 -37
  87. package/dist/repositories/organization.js.map +1 -1
  88. package/dist/repositories/permission.d.ts.map +1 -1
  89. package/dist/repositories/permission.js +27 -5
  90. package/dist/repositories/permission.js.map +1 -1
  91. package/dist/repositories/samlConnection.d.ts +28 -28
  92. package/dist/repositories/samlConnection.d.ts.map +1 -1
  93. package/dist/repositories/samlConnection.js +12 -4
  94. package/dist/repositories/samlConnection.js.map +1 -1
  95. package/dist/repositories/scimConnection.d.ts +38 -0
  96. package/dist/repositories/scimConnection.d.ts.map +1 -0
  97. package/dist/repositories/scimConnection.js +123 -0
  98. package/dist/repositories/scimConnection.js.map +1 -0
  99. package/dist/repositories/scimGroup.d.ts +36 -0
  100. package/dist/repositories/scimGroup.d.ts.map +1 -0
  101. package/dist/repositories/scimGroup.js +113 -0
  102. package/dist/repositories/scimGroup.js.map +1 -0
  103. package/dist/repositories/session.d.ts +23 -13
  104. package/dist/repositories/session.d.ts.map +1 -1
  105. package/dist/repositories/session.js +13 -1
  106. package/dist/repositories/session.js.map +1 -1
  107. package/dist/repositories/types.d.ts +112 -5
  108. package/dist/repositories/types.d.ts.map +1 -1
  109. package/dist/repositories/types.js +7 -1
  110. package/dist/repositories/types.js.map +1 -1
  111. package/dist/repositories/user.d.ts +23 -1
  112. package/dist/repositories/user.d.ts.map +1 -1
  113. package/dist/repositories/user.js +180 -4
  114. package/dist/repositories/user.js.map +1 -1
  115. package/dist/routes/admin/billing.js +4 -4
  116. package/dist/routes/admin/billing.js.map +1 -1
  117. package/dist/routes/admin/helpers.d.ts +16 -20
  118. package/dist/routes/admin/helpers.d.ts.map +1 -1
  119. package/dist/routes/admin/helpers.js +53 -10
  120. package/dist/routes/admin/helpers.js.map +1 -1
  121. package/dist/routes/admin/organizations.d.ts.map +1 -1
  122. package/dist/routes/admin/organizations.js +76 -69
  123. package/dist/routes/admin/organizations.js.map +1 -1
  124. package/dist/routes/admin/permissions.d.ts.map +1 -1
  125. package/dist/routes/admin/permissions.js +48 -14
  126. package/dist/routes/admin/permissions.js.map +1 -1
  127. package/dist/routes/admin/platform.d.ts.map +1 -1
  128. package/dist/routes/admin/platform.js +86 -35
  129. package/dist/routes/admin/platform.js.map +1 -1
  130. package/dist/routes/admin/sso.d.ts.map +1 -1
  131. package/dist/routes/admin/sso.js +143 -12
  132. package/dist/routes/admin/sso.js.map +1 -1
  133. package/dist/routes/admin/webhooks.js +8 -8
  134. package/dist/routes/admin/webhooks.js.map +1 -1
  135. package/dist/routes/apiKeys.d.ts.map +1 -1
  136. package/dist/routes/apiKeys.js +23 -5
  137. package/dist/routes/apiKeys.js.map +1 -1
  138. package/dist/routes/auth.d.ts.map +1 -1
  139. package/dist/routes/auth.js +112 -22
  140. package/dist/routes/auth.js.map +1 -1
  141. package/dist/routes/authz.d.ts.map +1 -1
  142. package/dist/routes/authz.js +16 -4
  143. package/dist/routes/authz.js.map +1 -1
  144. package/dist/routes/config.d.ts.map +1 -1
  145. package/dist/routes/config.js +16 -14
  146. package/dist/routes/config.js.map +1 -1
  147. package/dist/routes/federation.d.ts.map +1 -1
  148. package/dist/routes/federation.js +17 -3
  149. package/dist/routes/federation.js.map +1 -1
  150. package/dist/routes/magicLinks.d.ts.map +1 -1
  151. package/dist/routes/magicLinks.js +15 -3
  152. package/dist/routes/magicLinks.js.map +1 -1
  153. package/dist/routes/oauth.d.ts.map +1 -1
  154. package/dist/routes/oauth.js +22 -3
  155. package/dist/routes/oauth.js.map +1 -1
  156. package/dist/routes/oauth2.d.ts.map +1 -1
  157. package/dist/routes/oauth2.js +104 -11
  158. package/dist/routes/oauth2.js.map +1 -1
  159. package/dist/routes/oidcEnterprise.d.ts.map +1 -1
  160. package/dist/routes/oidcEnterprise.js +67 -21
  161. package/dist/routes/oidcEnterprise.js.map +1 -1
  162. package/dist/routes/password.d.ts.map +1 -1
  163. package/dist/routes/password.js.map +1 -1
  164. package/dist/routes/profile.js +4 -4
  165. package/dist/routes/profile.js.map +1 -1
  166. package/dist/routes/saml.d.ts +9 -0
  167. package/dist/routes/saml.d.ts.map +1 -1
  168. package/dist/routes/saml.js +187 -11
  169. package/dist/routes/saml.js.map +1 -1
  170. package/dist/routes/scim.d.ts +13 -0
  171. package/dist/routes/scim.d.ts.map +1 -1
  172. package/dist/routes/scim.js +885 -110
  173. package/dist/routes/scim.js.map +1 -1
  174. package/dist/routes/sdk.d.ts.map +1 -1
  175. package/dist/routes/sdk.js +24 -8
  176. package/dist/routes/sdk.js.map +1 -1
  177. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  178. package/dist/routes/serviceAccounts.js +2 -1
  179. package/dist/routes/serviceAccounts.js.map +1 -1
  180. package/dist/routes/setup.d.ts.map +1 -1
  181. package/dist/routes/setup.js +15 -16
  182. package/dist/routes/setup.js.map +1 -1
  183. package/dist/routes/smsOtp.js +1 -1
  184. package/dist/routes/smsOtp.js.map +1 -1
  185. package/dist/routes/totp.d.ts.map +1 -1
  186. package/dist/routes/totp.js +113 -23
  187. package/dist/routes/totp.js.map +1 -1
  188. package/dist/routes/webauthn.d.ts.map +1 -1
  189. package/dist/routes/webauthn.js +44 -8
  190. package/dist/routes/webauthn.js.map +1 -1
  191. package/dist/routes/workflows.d.ts.map +1 -1
  192. package/dist/routes/workflows.js +58 -25
  193. package/dist/routes/workflows.js.map +1 -1
  194. package/dist/sdk/index.d.ts.map +1 -1
  195. package/dist/sdk/index.js +141 -40
  196. package/dist/sdk/index.js.map +1 -1
  197. package/dist/sdk/types.d.ts +60 -29
  198. package/dist/sdk/types.d.ts.map +1 -1
  199. package/dist/services/application/authentication.d.ts +39 -1
  200. package/dist/services/application/authentication.d.ts.map +1 -1
  201. package/dist/services/application/authentication.js +43 -1
  202. package/dist/services/application/authentication.js.map +1 -1
  203. package/dist/services/application/identity.d.ts +10 -7
  204. package/dist/services/application/identity.d.ts.map +1 -1
  205. package/dist/services/application/identity.js +13 -10
  206. package/dist/services/application/identity.js.map +1 -1
  207. package/dist/services/application/organization.d.ts +11 -7
  208. package/dist/services/application/organization.d.ts.map +1 -1
  209. package/dist/services/application/organization.js +160 -12
  210. package/dist/services/application/organization.js.map +1 -1
  211. package/dist/services/applications.js +2 -2
  212. package/dist/services/applications.js.map +1 -1
  213. package/dist/services/audit.d.ts +1 -0
  214. package/dist/services/audit.d.ts.map +1 -1
  215. package/dist/services/audit.js +13 -0
  216. package/dist/services/audit.js.map +1 -1
  217. package/dist/services/cache.d.ts.map +1 -1
  218. package/dist/services/configuration/profiles.d.ts +4 -0
  219. package/dist/services/configuration/profiles.d.ts.map +1 -1
  220. package/dist/services/configuration/profiles.js +50 -0
  221. package/dist/services/configuration/profiles.js.map +1 -1
  222. package/dist/services/configuration.d.ts.map +1 -1
  223. package/dist/services/configuration.js.map +1 -1
  224. package/dist/services/connectors/google.d.ts.map +1 -1
  225. package/dist/services/connectors/google.js +3 -2
  226. package/dist/services/connectors/google.js.map +1 -1
  227. package/dist/services/connectors/oidc.d.ts.map +1 -1
  228. package/dist/services/connectors/oidc.js +6 -3
  229. package/dist/services/connectors/oidc.js.map +1 -1
  230. package/dist/services/connectors/zitadel.d.ts.map +1 -1
  231. package/dist/services/connectors/zitadel.js +4 -3
  232. package/dist/services/connectors/zitadel.js.map +1 -1
  233. package/dist/services/domain/authentication.d.ts +43 -4
  234. package/dist/services/domain/authentication.d.ts.map +1 -1
  235. package/dist/services/domain/authentication.js +82 -20
  236. package/dist/services/domain/authentication.js.map +1 -1
  237. package/dist/services/domain/authorization.d.ts +11 -0
  238. package/dist/services/domain/authorization.d.ts.map +1 -1
  239. package/dist/services/domain/authorization.js +36 -1
  240. package/dist/services/domain/authorization.js.map +1 -1
  241. package/dist/services/domain/identity.d.ts +21 -9
  242. package/dist/services/domain/identity.d.ts.map +1 -1
  243. package/dist/services/domain/identity.js +187 -10
  244. package/dist/services/domain/identity.js.map +1 -1
  245. package/dist/services/domain/organization.d.ts +6 -9
  246. package/dist/services/domain/organization.d.ts.map +1 -1
  247. package/dist/services/domain/organization.js +48 -30
  248. package/dist/services/domain/organization.js.map +1 -1
  249. package/dist/services/emailVerification.d.ts +2 -2
  250. package/dist/services/enterpriseSso.d.ts +13 -6
  251. package/dist/services/enterpriseSso.d.ts.map +1 -1
  252. package/dist/services/enterpriseSso.js +75 -6
  253. package/dist/services/enterpriseSso.js.map +1 -1
  254. package/dist/services/events/subscribers/auditLog.js +1 -1
  255. package/dist/services/events/subscribers/auditLog.js.map +1 -1
  256. package/dist/services/events/types.d.ts +7 -1
  257. package/dist/services/events/types.d.ts.map +1 -1
  258. package/dist/services/events/types.js.map +1 -1
  259. package/dist/services/events/validate.d.ts.map +1 -1
  260. package/dist/services/events/validate.js +27 -0
  261. package/dist/services/events/validate.js.map +1 -1
  262. package/dist/services/features.d.ts.map +1 -1
  263. package/dist/services/features.js.map +1 -1
  264. package/dist/services/federation.d.ts +6 -1
  265. package/dist/services/federation.d.ts.map +1 -1
  266. package/dist/services/federation.js +31 -4
  267. package/dist/services/federation.js.map +1 -1
  268. package/dist/services/ipControls.js +2 -2
  269. package/dist/services/ipControls.js.map +1 -1
  270. package/dist/services/magicLinks.d.ts +2 -2
  271. package/dist/services/mfa.d.ts +53 -0
  272. package/dist/services/mfa.d.ts.map +1 -0
  273. package/dist/services/mfa.js +157 -0
  274. package/dist/services/mfa.js.map +1 -0
  275. package/dist/services/oauth2.d.ts +16 -12
  276. package/dist/services/oauth2.d.ts.map +1 -1
  277. package/dist/services/oauth2.js +22 -13
  278. package/dist/services/oauth2.js.map +1 -1
  279. package/dist/services/oidcSecretFormat.d.ts +3 -0
  280. package/dist/services/oidcSecretFormat.d.ts.map +1 -0
  281. package/dist/services/oidcSecretFormat.js +5 -0
  282. package/dist/services/oidcSecretFormat.js.map +1 -0
  283. package/dist/services/organizations.d.ts +4 -16
  284. package/dist/services/organizations.d.ts.map +1 -1
  285. package/dist/services/organizations.js +0 -62
  286. package/dist/services/organizations.js.map +1 -1
  287. package/dist/services/permissions.d.ts.map +1 -1
  288. package/dist/services/permissions.js +9 -1
  289. package/dist/services/permissions.js.map +1 -1
  290. package/dist/services/plugins/registry.d.ts.map +1 -1
  291. package/dist/services/plugins/registry.js.map +1 -1
  292. package/dist/services/plugins/types.d.ts.map +1 -1
  293. package/dist/services/queue/bullmq.d.ts.map +1 -1
  294. package/dist/services/queue/inProcess.d.ts.map +1 -1
  295. package/dist/services/redis.d.ts +1 -1
  296. package/dist/services/redis.d.ts.map +1 -1
  297. package/dist/services/scimCredentials.d.ts +46 -0
  298. package/dist/services/scimCredentials.d.ts.map +1 -0
  299. package/dist/services/scimCredentials.js +123 -0
  300. package/dist/services/scimCredentials.js.map +1 -0
  301. package/dist/services/scimLegacyMigration.d.ts +12 -0
  302. package/dist/services/scimLegacyMigration.d.ts.map +1 -0
  303. package/dist/services/scimLegacyMigration.js +44 -0
  304. package/dist/services/scimLegacyMigration.js.map +1 -0
  305. package/dist/services/secrets/awsKms.d.ts +2 -2
  306. package/dist/services/secrets/awsKms.d.ts.map +1 -1
  307. package/dist/services/secrets/awsKms.js +3 -5
  308. package/dist/services/secrets/awsKms.js.map +1 -1
  309. package/dist/services/secrets/azureKeyVault.d.ts.map +1 -1
  310. package/dist/services/secrets/database.d.ts.map +1 -1
  311. package/dist/services/secrets/database.js.map +1 -1
  312. package/dist/services/secrets/environment.d.ts.map +1 -1
  313. package/dist/services/secrets/environment.js.map +1 -1
  314. package/dist/services/secrets/index.d.ts.map +1 -1
  315. package/dist/services/secrets/password.d.ts.map +1 -1
  316. package/dist/services/secrets/password.js +0 -4
  317. package/dist/services/secrets/password.js.map +1 -1
  318. package/dist/services/secrets/provider.d.ts +2 -3
  319. package/dist/services/secrets/provider.d.ts.map +1 -1
  320. package/dist/services/secrets/vault.d.ts.map +1 -1
  321. package/dist/services/setup/configWriter.d.ts.map +1 -1
  322. package/dist/services/setup/configWriter.js.map +1 -1
  323. package/dist/services/ssoEndpointPolicy.d.ts +8 -0
  324. package/dist/services/ssoEndpointPolicy.d.ts.map +1 -0
  325. package/dist/services/ssoEndpointPolicy.js +136 -0
  326. package/dist/services/ssoEndpointPolicy.js.map +1 -0
  327. package/dist/services/stepUp.d.ts +35 -0
  328. package/dist/services/stepUp.d.ts.map +1 -0
  329. package/dist/services/stepUp.js +65 -0
  330. package/dist/services/stepUp.js.map +1 -0
  331. package/dist/services/tokens.d.ts +37 -11
  332. package/dist/services/tokens.d.ts.map +1 -1
  333. package/dist/services/tokens.js +75 -14
  334. package/dist/services/tokens.js.map +1 -1
  335. package/dist/services/totp.d.ts +46 -0
  336. package/dist/services/totp.d.ts.map +1 -1
  337. package/dist/services/totp.js +178 -41
  338. package/dist/services/totp.js.map +1 -1
  339. package/dist/services/users.d.ts +20 -12
  340. package/dist/services/users.d.ts.map +1 -1
  341. package/dist/services/users.js +24 -51
  342. package/dist/services/users.js.map +1 -1
  343. package/dist/services/webauthn.d.ts +8 -4
  344. package/dist/services/webauthn.d.ts.map +1 -1
  345. package/dist/services/webauthn.js +4 -4
  346. package/dist/services/webauthn.js.map +1 -1
  347. package/dist/services/webhooks.d.ts +20 -20
  348. package/dist/services/workflows/engine.d.ts +4 -2
  349. package/dist/services/workflows/engine.d.ts.map +1 -1
  350. package/dist/services/workflows/engine.js +181 -12
  351. package/dist/services/workflows/engine.js.map +1 -1
  352. package/dist/services/workflows/steps.d.ts +2 -0
  353. package/dist/services/workflows/steps.d.ts.map +1 -1
  354. package/dist/services/workflows/steps.js +8 -75
  355. package/dist/services/workflows/steps.js.map +1 -1
  356. package/dist/setup-server.js.map +1 -1
  357. package/dist/types.d.ts +33 -4
  358. package/dist/types.d.ts.map +1 -1
  359. package/dist/types.js +26 -2
  360. package/dist/types.js.map +1 -1
  361. package/package.json +26 -3
  362. package/dist/tests/errors.test.d.ts +0 -2
  363. package/dist/tests/errors.test.d.ts.map +0 -1
  364. package/dist/tests/errors.test.js +0 -64
  365. package/dist/tests/errors.test.js.map +0 -1
  366. package/dist/tests/events.test.d.ts +0 -2
  367. package/dist/tests/events.test.d.ts.map +0 -1
  368. package/dist/tests/events.test.js +0 -45
  369. package/dist/tests/events.test.js.map +0 -1
  370. package/dist/tests/featureFlags.test.d.ts +0 -2
  371. package/dist/tests/featureFlags.test.d.ts.map +0 -1
  372. package/dist/tests/featureFlags.test.js +0 -24
  373. package/dist/tests/featureFlags.test.js.map +0 -1
  374. package/dist/tests/integration/queue.test.d.ts +0 -2
  375. package/dist/tests/integration/queue.test.d.ts.map +0 -1
  376. package/dist/tests/integration/queue.test.js +0 -49
  377. package/dist/tests/integration/queue.test.js.map +0 -1
  378. package/dist/tests/plugins.test.d.ts +0 -2
  379. package/dist/tests/plugins.test.d.ts.map +0 -1
  380. package/dist/tests/plugins.test.js +0 -56
  381. package/dist/tests/plugins.test.js.map +0 -1
  382. package/dist/tests/result.test.d.ts +0 -2
  383. package/dist/tests/result.test.d.ts.map +0 -1
  384. package/dist/tests/result.test.js +0 -46
  385. package/dist/tests/result.test.js.map +0 -1
  386. package/dist/tests/setup/configWriter.test.d.ts +0 -2
  387. package/dist/tests/setup/configWriter.test.d.ts.map +0 -1
  388. package/dist/tests/setup/configWriter.test.js +0 -55
  389. package/dist/tests/setup/configWriter.test.js.map +0 -1
  390. package/dist/tests/setup/validation.test.d.ts +0 -2
  391. package/dist/tests/setup/validation.test.d.ts.map +0 -1
  392. package/dist/tests/setup/validation.test.js +0 -26
  393. package/dist/tests/setup/validation.test.js.map +0 -1
  394. package/dist/tests/smoke.test.d.ts +0 -2
  395. package/dist/tests/smoke.test.d.ts.map +0 -1
  396. package/dist/tests/smoke.test.js +0 -124
  397. package/dist/tests/smoke.test.js.map +0 -1
  398. package/src/cli.ts +0 -172
  399. package/src/config.ts +0 -143
  400. package/src/container.ts +0 -48
  401. package/src/db/index.ts +0 -53
  402. package/src/db/migrations/0000_skinny_ben_parker.sql +0 -553
  403. package/src/db/migrations/0001_brief_joseph.sql +0 -10
  404. package/src/db/migrations/0002_add_account_lockout.sql +0 -3
  405. package/src/db/migrations/0003_steep_rachel_grey.sql +0 -1
  406. package/src/db/migrations/0004_clever_bill_hollister.sql +0 -20
  407. package/src/db/migrations/0005_steep_the_call.sql +0 -2
  408. package/src/db/migrations/0006_ambitious_boomer.sql +0 -17
  409. package/src/db/migrations/0007_greedy_vindicator.sql +0 -40
  410. package/src/db/migrations/meta/0000_snapshot.json +0 -2964
  411. package/src/db/migrations/meta/0001_snapshot.json +0 -3031
  412. package/src/db/migrations/meta/0003_snapshot.json +0 -3051
  413. package/src/db/migrations/meta/_journal.json +0 -62
  414. package/src/db/schema.ts +0 -676
  415. package/src/db/seed.ts +0 -146
  416. package/src/di.ts +0 -81
  417. package/src/index.ts +0 -326
  418. package/src/lib/errors.ts +0 -139
  419. package/src/lib/result.ts +0 -44
  420. package/src/lib/webhookSignature.ts +0 -41
  421. package/src/plugins/appContext.ts +0 -76
  422. package/src/plugins/audit.ts +0 -42
  423. package/src/plugins/auth.ts +0 -230
  424. package/src/plugins/metrics.ts +0 -41
  425. package/src/plugins/mtls.ts +0 -94
  426. package/src/plugins/permissions.ts +0 -29
  427. package/src/plugins/rateLimit.ts +0 -133
  428. package/src/plugins/requestLogger.ts +0 -25
  429. package/src/plugins/tracing.ts +0 -22
  430. package/src/repositories/apiKey.ts +0 -158
  431. package/src/repositories/application.ts +0 -70
  432. package/src/repositories/audit.ts +0 -32
  433. package/src/repositories/index.ts +0 -9
  434. package/src/repositories/oidcConnection.ts +0 -111
  435. package/src/repositories/organization.ts +0 -167
  436. package/src/repositories/permission.ts +0 -153
  437. package/src/repositories/samlConnection.ts +0 -96
  438. package/src/repositories/session.ts +0 -86
  439. package/src/repositories/types.ts +0 -134
  440. package/src/repositories/user.ts +0 -161
  441. package/src/routes/admin/billing.ts +0 -48
  442. package/src/routes/admin/helpers.ts +0 -50
  443. package/src/routes/admin/index.ts +0 -16
  444. package/src/routes/admin/organizations.ts +0 -299
  445. package/src/routes/admin/permissions.ts +0 -80
  446. package/src/routes/admin/platform.ts +0 -335
  447. package/src/routes/admin/sso.ts +0 -138
  448. package/src/routes/admin/webhooks.ts +0 -73
  449. package/src/routes/admin.ts +0 -1
  450. package/src/routes/apiKeys.ts +0 -60
  451. package/src/routes/auth.ts +0 -214
  452. package/src/routes/authz.ts +0 -38
  453. package/src/routes/config.ts +0 -67
  454. package/src/routes/emailVerification.ts +0 -73
  455. package/src/routes/federation.ts +0 -156
  456. package/src/routes/helpers.ts +0 -17
  457. package/src/routes/magicLinks.ts +0 -107
  458. package/src/routes/oauth.ts +0 -167
  459. package/src/routes/oauth2.ts +0 -284
  460. package/src/routes/oidcEnterprise.ts +0 -166
  461. package/src/routes/password.ts +0 -90
  462. package/src/routes/profile.ts +0 -44
  463. package/src/routes/saml.ts +0 -209
  464. package/src/routes/scim.ts +0 -199
  465. package/src/routes/sdk.ts +0 -141
  466. package/src/routes/serviceAccounts.ts +0 -124
  467. package/src/routes/sessions.ts +0 -62
  468. package/src/routes/setup.ts +0 -315
  469. package/src/routes/smsOtp.ts +0 -67
  470. package/src/routes/totp.ts +0 -122
  471. package/src/routes/webauthn.ts +0 -147
  472. package/src/routes/workflows.ts +0 -157
  473. package/src/sdk/index.ts +0 -152
  474. package/src/sdk/types.ts +0 -54
  475. package/src/services/anomalyDetection.ts +0 -73
  476. package/src/services/application/authentication.ts +0 -75
  477. package/src/services/application/identity.ts +0 -56
  478. package/src/services/application/index.ts +0 -3
  479. package/src/services/application/organization.ts +0 -77
  480. package/src/services/applications.ts +0 -89
  481. package/src/services/audit.ts +0 -41
  482. package/src/services/auditExport.ts +0 -59
  483. package/src/services/billing.ts +0 -87
  484. package/src/services/cache.ts +0 -131
  485. package/src/services/configuration/profiles.ts +0 -115
  486. package/src/services/configuration.ts +0 -120
  487. package/src/services/connectors/google.ts +0 -92
  488. package/src/services/connectors/oidc.ts +0 -111
  489. package/src/services/connectors/registry.ts +0 -124
  490. package/src/services/connectors/types.ts +0 -38
  491. package/src/services/connectors/zitadel.ts +0 -77
  492. package/src/services/devices.ts +0 -76
  493. package/src/services/domain/authentication.ts +0 -279
  494. package/src/services/domain/authorization.ts +0 -49
  495. package/src/services/domain/identity.ts +0 -108
  496. package/src/services/domain/index.ts +0 -4
  497. package/src/services/domain/organization.ts +0 -114
  498. package/src/services/email.ts +0 -167
  499. package/src/services/emailVerification.ts +0 -75
  500. package/src/services/enterpriseSso.ts +0 -58
  501. package/src/services/events/bus.ts +0 -43
  502. package/src/services/events/subscribers/anomaly.ts +0 -13
  503. package/src/services/events/subscribers/auditLog.ts +0 -21
  504. package/src/services/events/subscribers/webhook.ts +0 -39
  505. package/src/services/events/subscribers/webhookDispatch.ts +0 -14
  506. package/src/services/events/types.ts +0 -106
  507. package/src/services/events/validate.ts +0 -118
  508. package/src/services/featureFlags.ts +0 -90
  509. package/src/services/features.ts +0 -22
  510. package/src/services/federation.ts +0 -30
  511. package/src/services/hibp.ts +0 -28
  512. package/src/services/ipControls.ts +0 -99
  513. package/src/services/magicLinks.ts +0 -51
  514. package/src/services/oauth2.ts +0 -216
  515. package/src/services/organizations.ts +0 -171
  516. package/src/services/permissions.ts +0 -146
  517. package/src/services/plugins/registry.ts +0 -242
  518. package/src/services/plugins/types.ts +0 -98
  519. package/src/services/queue/bullmq.ts +0 -104
  520. package/src/services/queue/inProcess.ts +0 -75
  521. package/src/services/queue/index.ts +0 -19
  522. package/src/services/queue/types.ts +0 -26
  523. package/src/services/redis.ts +0 -16
  524. package/src/services/secrets/awsKms.ts +0 -97
  525. package/src/services/secrets/azureKeyVault.ts +0 -171
  526. package/src/services/secrets/database.ts +0 -166
  527. package/src/services/secrets/environment.ts +0 -117
  528. package/src/services/secrets/index.ts +0 -50
  529. package/src/services/secrets/password.ts +0 -73
  530. package/src/services/secrets/provider.ts +0 -36
  531. package/src/services/secrets/vault.ts +0 -149
  532. package/src/services/secrets.ts +0 -2
  533. package/src/services/serviceAccounts.ts +0 -74
  534. package/src/services/setup/configWriter.ts +0 -200
  535. package/src/services/setup/diagnostics.ts +0 -76
  536. package/src/services/setup/token.ts +0 -42
  537. package/src/services/setup/types.ts +0 -40
  538. package/src/services/setup/validation.ts +0 -205
  539. package/src/services/sms.ts +0 -81
  540. package/src/services/smsOtp.ts +0 -74
  541. package/src/services/tokens.ts +0 -287
  542. package/src/services/totp.ts +0 -113
  543. package/src/services/users.ts +0 -239
  544. package/src/services/webauthn.ts +0 -193
  545. package/src/services/webhooks.ts +0 -190
  546. package/src/services/workflows/engine.ts +0 -125
  547. package/src/services/workflows/steps.ts +0 -129
  548. package/src/services/zitadel.ts +0 -277
  549. package/src/setup-server.ts +0 -71
  550. package/src/tests/errors.test.ts +0 -74
  551. package/src/tests/events.test.ts +0 -52
  552. package/src/tests/featureFlags.test.ts +0 -26
  553. package/src/tests/integration/queue.test.ts +0 -54
  554. package/src/tests/plugins.test.ts +0 -73
  555. package/src/tests/result.test.ts +0 -52
  556. package/src/tests/setup/configWriter.test.ts +0 -69
  557. package/src/tests/setup/validation.test.ts +0 -29
  558. package/src/tests/smoke.test.ts +0 -136
  559. 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
- }