@adonis-agora/authkit-server 0.34.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 (389) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +158 -0
  3. package/build/assets/grafana/authkit-dashboard.json +118 -0
  4. package/build/commands/clients_create.d.ts +27 -0
  5. package/build/commands/clients_create.js +121 -0
  6. package/build/commands/commands.json +292 -0
  7. package/build/commands/configure.d.ts +2 -0
  8. package/build/commands/configure.js +45 -0
  9. package/build/commands/doctor.d.ts +10 -0
  10. package/build/commands/doctor.js +113 -0
  11. package/build/commands/eject.d.ts +11 -0
  12. package/build/commands/eject.js +96 -0
  13. package/build/commands/expire_scan.d.ts +28 -0
  14. package/build/commands/expire_scan.js +92 -0
  15. package/build/commands/import_users.d.ts +17 -0
  16. package/build/commands/import_users.js +80 -0
  17. package/build/commands/keys_rotate.d.ts +21 -0
  18. package/build/commands/keys_rotate.js +126 -0
  19. package/build/commands/main.d.ts +12 -0
  20. package/build/commands/main.js +38 -0
  21. package/build/commands/settings_get.d.ts +18 -0
  22. package/build/commands/settings_get.js +43 -0
  23. package/build/commands/settings_list.d.ts +17 -0
  24. package/build/commands/settings_list.js +39 -0
  25. package/build/commands/settings_set.d.ts +20 -0
  26. package/build/commands/settings_set.js +55 -0
  27. package/build/commands/settings_unset.d.ts +18 -0
  28. package/build/commands/settings_unset.js +46 -0
  29. package/build/commands/ui_preset.d.ts +4 -0
  30. package/build/commands/ui_preset.js +32 -0
  31. package/build/database/migrations/make_authkit_oidc_table.d.ts +6 -0
  32. package/build/database/migrations/make_authkit_oidc_table.js +19 -0
  33. package/build/host/ui/admin.html +29 -0
  34. package/build/host/views/account/apps.edge +59 -0
  35. package/build/host/views/account/confirm.edge +70 -0
  36. package/build/host/views/account/email-confirmed.edge +16 -0
  37. package/build/host/views/account/login.edge +33 -0
  38. package/build/host/views/account/mfa.edge +152 -0
  39. package/build/host/views/account/orgs.edge +58 -0
  40. package/build/host/views/account/security.edge +215 -0
  41. package/build/host/views/account/tokens.edge +75 -0
  42. package/build/host/views/consent.edge +20 -0
  43. package/build/host/views/forgot.edge +43 -0
  44. package/build/host/views/login.edge +251 -0
  45. package/build/host/views/maintenance.edge +32 -0
  46. package/build/host/views/mfa-challenge.edge +107 -0
  47. package/build/host/views/otp-unlock.edge +40 -0
  48. package/build/host/views/partials/styles.edge +2 -0
  49. package/build/host/views/reset.edge +30 -0
  50. package/build/host/views/signup.edge +62 -0
  51. package/build/host/views/verify-email.edge +17 -0
  52. package/build/index.d.ts +115 -0
  53. package/build/index.js +76 -0
  54. package/build/password/common_passwords.txt +10000 -0
  55. package/build/providers/authkit_server_provider.d.ts +27 -0
  56. package/build/providers/authkit_server_provider.js +242 -0
  57. package/build/src/accounts/account_store.d.ts +578 -0
  58. package/build/src/accounts/account_store.js +60 -0
  59. package/build/src/accounts/lucid_account_store.d.ts +156 -0
  60. package/build/src/accounts/lucid_account_store.js +294 -0
  61. package/build/src/accounts/lucid_store/core.d.ts +9 -0
  62. package/build/src/accounts/lucid_store/core.js +306 -0
  63. package/build/src/accounts/lucid_store/mfa.d.ts +15 -0
  64. package/build/src/accounts/lucid_store/mfa.js +108 -0
  65. package/build/src/accounts/lucid_store/organizations.d.ts +13 -0
  66. package/build/src/accounts/lucid_store/organizations.js +294 -0
  67. package/build/src/accounts/lucid_store/password_hygiene.d.ts +20 -0
  68. package/build/src/accounts/lucid_store/password_hygiene.js +130 -0
  69. package/build/src/accounts/lucid_store/provider_identity.d.ts +8 -0
  70. package/build/src/accounts/lucid_store/provider_identity.js +59 -0
  71. package/build/src/accounts/lucid_store/shared.d.ts +113 -0
  72. package/build/src/accounts/lucid_store/shared.js +130 -0
  73. package/build/src/accounts/lucid_store/status_profile.d.ts +34 -0
  74. package/build/src/accounts/lucid_store/status_profile.js +100 -0
  75. package/build/src/accounts/lucid_store/webauthn.d.ts +8 -0
  76. package/build/src/accounts/lucid_store/webauthn.js +140 -0
  77. package/build/src/accounts/lucid_stores.d.ts +45 -0
  78. package/build/src/accounts/lucid_stores.js +30 -0
  79. package/build/src/adapters/adapter_contract.d.ts +37 -0
  80. package/build/src/adapters/adapter_contract.js +1 -0
  81. package/build/src/adapters/database_adapter.d.ts +21 -0
  82. package/build/src/adapters/database_adapter.js +79 -0
  83. package/build/src/adapters/factory.d.ts +30 -0
  84. package/build/src/adapters/factory.js +43 -0
  85. package/build/src/adapters/redis_adapter.d.ts +24 -0
  86. package/build/src/adapters/redis_adapter.js +122 -0
  87. package/build/src/audit/audit_sink.d.ts +63 -0
  88. package/build/src/audit/audit_sink.js +1 -0
  89. package/build/src/audit/lucid_audit_sink.d.ts +10 -0
  90. package/build/src/audit/lucid_audit_sink.js +99 -0
  91. package/build/src/commands/expire_scan_command.d.ts +60 -0
  92. package/build/src/commands/expire_scan_command.js +229 -0
  93. package/build/src/commands/import_clients.d.ts +40 -0
  94. package/build/src/commands/import_clients.js +79 -0
  95. package/build/src/commands/import_users.d.ts +51 -0
  96. package/build/src/commands/import_users.js +94 -0
  97. package/build/src/commands/resolve_config.d.ts +13 -0
  98. package/build/src/commands/resolve_config.js +18 -0
  99. package/build/src/commands/settings_commands.d.ts +47 -0
  100. package/build/src/commands/settings_commands.js +270 -0
  101. package/build/src/controllers/oidc_callback_controller.d.ts +22 -0
  102. package/build/src/controllers/oidc_callback_controller.js +33 -0
  103. package/build/src/define_config.d.ts +772 -0
  104. package/build/src/define_config.js +351 -0
  105. package/build/src/doctor/checks.d.ts +197 -0
  106. package/build/src/doctor/checks.js +858 -0
  107. package/build/src/events/dispatcher.d.ts +45 -0
  108. package/build/src/events/dispatcher.js +117 -0
  109. package/build/src/host/account_api/account_api_controller.d.ts +245 -0
  110. package/build/src/host/account_api/account_api_controller.js +827 -0
  111. package/build/src/host/account_deletion_ops.d.ts +80 -0
  112. package/build/src/host/account_deletion_ops.js +118 -0
  113. package/build/src/host/account_deletion_service.d.ts +63 -0
  114. package/build/src/host/account_deletion_service.js +133 -0
  115. package/build/src/host/account_export_service.d.ts +76 -0
  116. package/build/src/host/account_export_service.js +140 -0
  117. package/build/src/host/account_home.d.ts +11 -0
  118. package/build/src/host/account_home.js +11 -0
  119. package/build/src/host/account_lockout.d.ts +86 -0
  120. package/build/src/host/account_lockout.js +185 -0
  121. package/build/src/host/active_org_cookie.d.ts +28 -0
  122. package/build/src/host/active_org_cookie.js +47 -0
  123. package/build/src/host/admin_api/admin_api_guard.d.ts +16 -0
  124. package/build/src/host/admin_api/admin_api_guard.js +59 -0
  125. package/build/src/host/admin_api/admin_orgs_service.d.ts +125 -0
  126. package/build/src/host/admin_api/admin_orgs_service.js +324 -0
  127. package/build/src/host/admin_api/admin_users_service.d.ts +163 -0
  128. package/build/src/host/admin_api/admin_users_service.js +308 -0
  129. package/build/src/host/admin_api/api_clients_controller.d.ts +54 -0
  130. package/build/src/host/admin_api/api_clients_controller.js +89 -0
  131. package/build/src/host/admin_api/api_keys_controller.d.ts +19 -0
  132. package/build/src/host/admin_api/api_keys_controller.js +36 -0
  133. package/build/src/host/admin_api/api_misc_controller.d.ts +19 -0
  134. package/build/src/host/admin_api/api_misc_controller.js +44 -0
  135. package/build/src/host/admin_api/api_orgs_controller.d.ts +108 -0
  136. package/build/src/host/admin_api/api_orgs_controller.js +189 -0
  137. package/build/src/host/admin_api/api_settings_controller.d.ts +55 -0
  138. package/build/src/host/admin_api/api_settings_controller.js +134 -0
  139. package/build/src/host/admin_api/api_users_controller.d.ts +108 -0
  140. package/build/src/host/admin_api/api_users_controller.js +187 -0
  141. package/build/src/host/admin_api/dto.d.ts +131 -0
  142. package/build/src/host/admin_api/dto.js +122 -0
  143. package/build/src/host/admin_api/token_verify_service.d.ts +34 -0
  144. package/build/src/host/admin_api/token_verify_service.js +74 -0
  145. package/build/src/host/admin_clients_service.d.ts +88 -0
  146. package/build/src/host/admin_clients_service.js +181 -0
  147. package/build/src/host/admin_console/admin_shell_controller.d.ts +27 -0
  148. package/build/src/host/admin_console/admin_shell_controller.js +167 -0
  149. package/build/src/host/admin_console/console_audit_controller.d.ts +17 -0
  150. package/build/src/host/admin_console/console_audit_controller.js +25 -0
  151. package/build/src/host/admin_console/console_clients_controller.d.ts +53 -0
  152. package/build/src/host/admin_console/console_clients_controller.js +102 -0
  153. package/build/src/host/admin_console/console_impersonation_controller.d.ts +23 -0
  154. package/build/src/host/admin_console/console_impersonation_controller.js +45 -0
  155. package/build/src/host/admin_console/console_keys_controller.d.ts +24 -0
  156. package/build/src/host/admin_console/console_keys_controller.js +41 -0
  157. package/build/src/host/admin_console/console_orgs_controller.d.ts +96 -0
  158. package/build/src/host/admin_console/console_orgs_controller.js +238 -0
  159. package/build/src/host/admin_console/console_overview_controller.d.ts +27 -0
  160. package/build/src/host/admin_console/console_overview_controller.js +44 -0
  161. package/build/src/host/admin_console/console_roles_controller.d.ts +31 -0
  162. package/build/src/host/admin_console/console_roles_controller.js +108 -0
  163. package/build/src/host/admin_console/console_sessions_controller.d.ts +91 -0
  164. package/build/src/host/admin_console/console_sessions_controller.js +125 -0
  165. package/build/src/host/admin_console/console_settings_controller.d.ts +47 -0
  166. package/build/src/host/admin_console/console_settings_controller.js +115 -0
  167. package/build/src/host/admin_console/console_users_controller.d.ts +110 -0
  168. package/build/src/host/admin_console/console_users_controller.js +212 -0
  169. package/build/src/host/admin_prefix.d.ts +50 -0
  170. package/build/src/host/admin_prefix.js +77 -0
  171. package/build/src/host/admin_sessions_service.d.ts +119 -0
  172. package/build/src/host/admin_sessions_service.js +284 -0
  173. package/build/src/host/admin_stats_service.d.ts +44 -0
  174. package/build/src/host/admin_stats_service.js +130 -0
  175. package/build/src/host/admin_validators.d.ts +247 -0
  176. package/build/src/host/admin_validators.js +197 -0
  177. package/build/src/host/augmentations.d.ts +12 -0
  178. package/build/src/host/augmentations.js +1 -0
  179. package/build/src/host/auth_host_config.d.ts +22 -0
  180. package/build/src/host/auth_host_config.js +13 -0
  181. package/build/src/host/avatar_storage.d.ts +68 -0
  182. package/build/src/host/avatar_storage.js +166 -0
  183. package/build/src/host/bot_protection.d.ts +187 -0
  184. package/build/src/host/bot_protection.js +132 -0
  185. package/build/src/host/branding.d.ts +19 -0
  186. package/build/src/host/branding.js +8 -0
  187. package/build/src/host/config_locks.d.ts +38 -0
  188. package/build/src/host/config_locks.js +70 -0
  189. package/build/src/host/console_session.d.ts +27 -0
  190. package/build/src/host/console_session.js +36 -0
  191. package/build/src/host/controllers/account_apps_controller.d.ts +15 -0
  192. package/build/src/host/controllers/account_apps_controller.js +61 -0
  193. package/build/src/host/controllers/account_confirm_controller.d.ts +24 -0
  194. package/build/src/host/controllers/account_confirm_controller.js +144 -0
  195. package/build/src/host/controllers/account_mfa_controller.d.ts +28 -0
  196. package/build/src/host/controllers/account_mfa_controller.js +208 -0
  197. package/build/src/host/controllers/account_orgs_controller.d.ts +80 -0
  198. package/build/src/host/controllers/account_orgs_controller.js +401 -0
  199. package/build/src/host/controllers/account_security_controller.d.ts +43 -0
  200. package/build/src/host/controllers/account_security_controller.js +546 -0
  201. package/build/src/host/controllers/account_session_controller.d.ts +21 -0
  202. package/build/src/host/controllers/account_session_controller.js +113 -0
  203. package/build/src/host/controllers/account_tokens_controller.d.ts +7 -0
  204. package/build/src/host/controllers/account_tokens_controller.js +67 -0
  205. package/build/src/host/controllers/interaction_controller.d.ts +125 -0
  206. package/build/src/host/controllers/interaction_controller.js +981 -0
  207. package/build/src/host/controllers/pat_introspection_controller.d.ts +22 -0
  208. package/build/src/host/controllers/pat_introspection_controller.js +46 -0
  209. package/build/src/host/controllers/registration_controller.d.ts +18 -0
  210. package/build/src/host/controllers/registration_controller.js +382 -0
  211. package/build/src/host/controllers/social_controller.d.ts +8 -0
  212. package/build/src/host/controllers/social_controller.js +89 -0
  213. package/build/src/host/csrf.d.ts +29 -0
  214. package/build/src/host/csrf.js +14 -0
  215. package/build/src/host/default_mailer.d.ts +112 -0
  216. package/build/src/host/default_mailer.js +417 -0
  217. package/build/src/host/durable/account_deletion_workflow.d.ts +48 -0
  218. package/build/src/host/durable/account_deletion_workflow.js +86 -0
  219. package/build/src/host/durable/account_export_workflow.d.ts +68 -0
  220. package/build/src/host/durable/account_export_workflow.js +93 -0
  221. package/build/src/host/durable/index.d.ts +68 -0
  222. package/build/src/host/durable/index.js +77 -0
  223. package/build/src/host/email_templates.d.ts +39 -0
  224. package/build/src/host/email_templates.js +69 -0
  225. package/build/src/host/geo.d.ts +22 -0
  226. package/build/src/host/geo.js +39 -0
  227. package/build/src/host/i18n.d.ts +1416 -0
  228. package/build/src/host/i18n.js +1583 -0
  229. package/build/src/host/impersonation.d.ts +25 -0
  230. package/build/src/host/impersonation.js +31 -0
  231. package/build/src/host/key_rotation.d.ts +14 -0
  232. package/build/src/host/key_rotation.js +27 -0
  233. package/build/src/host/key_rotation_actions.d.ts +42 -0
  234. package/build/src/host/key_rotation_actions.js +27 -0
  235. package/build/src/host/login_attempt.d.ts +98 -0
  236. package/build/src/host/login_attempt.js +211 -0
  237. package/build/src/host/login_notify.d.ts +27 -0
  238. package/build/src/host/login_notify.js +142 -0
  239. package/build/src/host/middleware/account_auth.d.ts +7 -0
  240. package/build/src/host/middleware/account_auth.js +11 -0
  241. package/build/src/host/otp_lockout.d.ts +103 -0
  242. package/build/src/host/otp_lockout.js +221 -0
  243. package/build/src/host/rate_limit.d.ts +39 -0
  244. package/build/src/host/rate_limit.js +94 -0
  245. package/build/src/host/register_auth_host.d.ts +97 -0
  246. package/build/src/host/register_auth_host.js +466 -0
  247. package/build/src/host/renderers/edge_renderer.d.ts +12 -0
  248. package/build/src/host/renderers/edge_renderer.js +38 -0
  249. package/build/src/host/renderers/inertia_renderer.d.ts +70 -0
  250. package/build/src/host/renderers/inertia_renderer.js +54 -0
  251. package/build/src/host/runtime_settings.d.ts +181 -0
  252. package/build/src/host/runtime_settings.js +307 -0
  253. package/build/src/host/runtime_toggles.d.ts +807 -0
  254. package/build/src/host/runtime_toggles.js +784 -0
  255. package/build/src/host/security_notice_service.d.ts +36 -0
  256. package/build/src/host/security_notice_service.js +87 -0
  257. package/build/src/host/session_context.d.ts +23 -0
  258. package/build/src/host/session_context.js +89 -0
  259. package/build/src/host/sudo_mode.d.ts +56 -0
  260. package/build/src/host/sudo_mode.js +99 -0
  261. package/build/src/host/svg_chart.d.ts +15 -0
  262. package/build/src/host/svg_chart.js +45 -0
  263. package/build/src/host/trusted_device.d.ts +61 -0
  264. package/build/src/host/trusted_device.js +65 -0
  265. package/build/src/host/ui-dist/assets/index-CRWcmsex.js +137 -0
  266. package/build/src/host/ui-dist/assets/index-DTSmD4RU.css +1 -0
  267. package/build/src/host/ui-dist/index.html +17 -0
  268. package/build/src/host/user_agent.d.ts +18 -0
  269. package/build/src/host/user_agent.js +50 -0
  270. package/build/src/host/validators.d.ts +127 -0
  271. package/build/src/host/validators.js +53 -0
  272. package/build/src/keys/jwks_manager.d.ts +6 -0
  273. package/build/src/keys/jwks_manager.js +11 -0
  274. package/build/src/keys/keystore.d.ts +52 -0
  275. package/build/src/keys/keystore.js +68 -0
  276. package/build/src/keys/keystore_codec.d.ts +20 -0
  277. package/build/src/keys/keystore_codec.js +42 -0
  278. package/build/src/keys/keystore_crypto.d.ts +9 -0
  279. package/build/src/keys/keystore_crypto.js +27 -0
  280. package/build/src/keys/keystore_manager.d.ts +43 -0
  281. package/build/src/keys/keystore_manager.js +104 -0
  282. package/build/src/keys/keystore_vault.d.ts +113 -0
  283. package/build/src/keys/keystore_vault.js +265 -0
  284. package/build/src/mixins/json_column.d.ts +33 -0
  285. package/build/src/mixins/json_column.js +38 -0
  286. package/build/src/mixins/with_audit_log.d.ts +19 -0
  287. package/build/src/mixins/with_audit_log.js +39 -0
  288. package/build/src/mixins/with_auth_user.d.ts +24 -0
  289. package/build/src/mixins/with_auth_user.js +46 -0
  290. package/build/src/mixins/with_credentials.d.ts +20 -0
  291. package/build/src/mixins/with_credentials.js +29 -0
  292. package/build/src/mixins/with_mfa.d.ts +35 -0
  293. package/build/src/mixins/with_mfa.js +21 -0
  294. package/build/src/mixins/with_personal_access_token.d.ts +19 -0
  295. package/build/src/mixins/with_personal_access_token.js +42 -0
  296. package/build/src/mixins/with_provider_identity.d.ts +20 -0
  297. package/build/src/mixins/with_provider_identity.js +32 -0
  298. package/build/src/mixins/with_webauthn_credential.d.ts +37 -0
  299. package/build/src/mixins/with_webauthn_credential.js +46 -0
  300. package/build/src/observability/diagnostics_bridge.d.ts +6 -0
  301. package/build/src/observability/diagnostics_bridge.js +27 -0
  302. package/build/src/observability/metrics_controller.d.ts +5 -0
  303. package/build/src/observability/metrics_controller.js +24 -0
  304. package/build/src/observability/metrics_service.d.ts +2 -0
  305. package/build/src/observability/metrics_service.js +7 -0
  306. package/build/src/observability/otel_recorder.d.ts +10 -0
  307. package/build/src/observability/otel_recorder.js +59 -0
  308. package/build/src/observability/telescope/data_providers.d.ts +24 -0
  309. package/build/src/observability/telescope/data_providers.js +235 -0
  310. package/build/src/observability/telescope/extension.d.ts +29 -0
  311. package/build/src/observability/telescope/extension.js +167 -0
  312. package/build/src/observability/telescope/index.d.ts +8 -0
  313. package/build/src/observability/telescope/index.js +8 -0
  314. package/build/src/observability/wire_provider_events.d.ts +12 -0
  315. package/build/src/observability/wire_provider_events.js +30 -0
  316. package/build/src/password/common_passwords.d.ts +31 -0
  317. package/build/src/password/common_passwords.js +73 -0
  318. package/build/src/password/password_manager.d.ts +163 -0
  319. package/build/src/password/password_manager.js +191 -0
  320. package/build/src/password/policy.d.ts +71 -0
  321. package/build/src/password/policy.js +55 -0
  322. package/build/src/password/pwned.d.ts +36 -0
  323. package/build/src/password/pwned.js +52 -0
  324. package/build/src/pat/lucid_pat_store.d.ts +6 -0
  325. package/build/src/pat/lucid_pat_store.js +62 -0
  326. package/build/src/pat/pat_store.d.ts +31 -0
  327. package/build/src/pat/pat_store.js +1 -0
  328. package/build/src/pat/pat_tokens.d.ts +4 -0
  329. package/build/src/pat/pat_tokens.js +9 -0
  330. package/build/src/provider/build_provider.d.ts +45 -0
  331. package/build/src/provider/build_provider.js +219 -0
  332. package/build/src/provider/device_sources.d.ts +6 -0
  333. package/build/src/provider/device_sources.js +65 -0
  334. package/build/src/provider/interaction_actions.d.ts +36 -0
  335. package/build/src/provider/interaction_actions.js +55 -0
  336. package/build/src/provider/key_rotation_scheduler.d.ts +28 -0
  337. package/build/src/provider/key_rotation_scheduler.js +40 -0
  338. package/build/src/provider/keystore_reload.d.ts +21 -0
  339. package/build/src/provider/keystore_reload.js +39 -0
  340. package/build/src/provider/logout_sources.d.ts +13 -0
  341. package/build/src/provider/logout_sources.js +64 -0
  342. package/build/src/provider/oidc_service.d.ts +81 -0
  343. package/build/src/provider/oidc_service.js +254 -0
  344. package/build/src/provider/single_flight_lock.d.ts +18 -0
  345. package/build/src/provider/single_flight_lock.js +31 -0
  346. package/build/src/provider/token_exchange.d.ts +21 -0
  347. package/build/src/provider/token_exchange.js +124 -0
  348. package/build/src/register_routes.d.ts +16 -0
  349. package/build/src/register_routes.js +21 -0
  350. package/build/src/schema/ensure.d.ts +41 -0
  351. package/build/src/schema/ensure.js +262 -0
  352. package/build/stubs/config/authkit.stub +20 -0
  353. package/build/stubs/config/authkit_react.stub +52 -0
  354. package/build/stubs/main.d.ts +1 -0
  355. package/build/stubs/main.js +2 -0
  356. package/build/stubs/models/auth_user.stub +22 -0
  357. package/build/stubs/ui/edge/views/consent.edge +13 -0
  358. package/build/stubs/ui/edge/views/login.edge +19 -0
  359. package/build/stubs/ui/react/components/auth_shell.tsx +67 -0
  360. package/build/stubs/ui/react/pages/account/login.tsx +56 -0
  361. package/build/stubs/ui/react/pages/account/mfa.tsx +132 -0
  362. package/build/stubs/ui/react/pages/account/tokens.tsx +88 -0
  363. package/build/stubs/ui/react/pages/consent.tsx +39 -0
  364. package/build/stubs/ui/react/pages/forgot.tsx +44 -0
  365. package/build/stubs/ui/react/pages/login.tsx +171 -0
  366. package/build/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
  367. package/build/stubs/ui/react/pages/reset.tsx +58 -0
  368. package/build/stubs/ui/react/pages/signup.tsx +78 -0
  369. package/build/stubs/ui/react/pages/verify-email.tsx +24 -0
  370. package/build/types.d.ts +7 -0
  371. package/build/types.js +1 -0
  372. package/package.json +147 -0
  373. package/stubs/config/authkit.stub +20 -0
  374. package/stubs/config/authkit_react.stub +52 -0
  375. package/stubs/main.ts +2 -0
  376. package/stubs/models/auth_user.stub +22 -0
  377. package/stubs/ui/edge/views/consent.edge +13 -0
  378. package/stubs/ui/edge/views/login.edge +19 -0
  379. package/stubs/ui/react/components/auth_shell.tsx +67 -0
  380. package/stubs/ui/react/pages/account/login.tsx +56 -0
  381. package/stubs/ui/react/pages/account/mfa.tsx +132 -0
  382. package/stubs/ui/react/pages/account/tokens.tsx +88 -0
  383. package/stubs/ui/react/pages/consent.tsx +39 -0
  384. package/stubs/ui/react/pages/forgot.tsx +44 -0
  385. package/stubs/ui/react/pages/login.tsx +171 -0
  386. package/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
  387. package/stubs/ui/react/pages/reset.tsx +58 -0
  388. package/stubs/ui/react/pages/signup.tsx +78 -0
  389. package/stubs/ui/react/pages/verify-email.tsx +24 -0
@@ -0,0 +1,81 @@
1
+ import { type MetricsRecorder } from '@adonis-agora/authkit-core';
2
+ import type { ResolvedServerConfig } from '../define_config.js';
3
+ import { buildProvider, type SessionTtlHolder, type TokenTtlHolder } from './build_provider.js';
4
+ import { type InteractionActions } from './interaction_actions.js';
5
+ import { type ManagedKeyInfo } from '../keys/keystore.js';
6
+ import type { KeystoreManager } from '../keys/keystore_manager.js';
7
+ export declare class OidcService {
8
+ #private;
9
+ get provider(): ReturnType<typeof buildProvider>;
10
+ get callback(): (req: any, res: any) => void;
11
+ get interactions(): InteractionActions;
12
+ /** Pathname do issuer sem barra final (ex.: `/oidc`). Vazio quando montado na raiz. */
13
+ readonly mountPath: string;
14
+ readonly recorder: MetricsRecorder;
15
+ /** Holder mutável dos TTLs de sessão OIDC (lido sincronamente pelo oidc-provider). */
16
+ readonly sessionTtlHolder: SessionTtlHolder;
17
+ /** Holder mutável dos TTLs de access/id/refresh tokens (lido sincronamente pelo oidc-provider). */
18
+ readonly tokenTtlHolder: TokenTtlHolder;
19
+ get config(): ResolvedServerConfig;
20
+ /** @internal Loader de JWKS do cofre (usado por reloadKeys). */
21
+ get jwksLoader(): (() => Promise<{
22
+ keys: Record<string, any>[];
23
+ }>) | undefined;
24
+ /** @internal Token barato de mudança do cofre (usado pelo poll de reload). */
25
+ get keystoreHead(): (() => Promise<string | null>) | undefined;
26
+ constructor(config: ResolvedServerConfig, appKey: string, recorder?: MetricsRecorder, deps?: {
27
+ /** Relê o keystore do cofre e devolve o JWKS (sem `iat`). Ausente → reloadKeys é no-op. */
28
+ jwksLoader?: () => Promise<{
29
+ keys: Record<string, any>[];
30
+ }>;
31
+ /** Token barato de mudança do cofre (kid/etag/mtime) p/ o poll. */
32
+ keystoreHead?: () => Promise<string | null>;
33
+ /** Fábrica do KeystoreManager (necessária para rotateKeys e keystoreAgeDays). */
34
+ keystoreManager?: () => Promise<KeystoreManager>;
35
+ });
36
+ /**
37
+ * Recarrega as chaves de assinatura AO VIVO: relê o keystore do cofre e reconstrói
38
+ * o provider com o JWKS novo, trocando a instância atomicamente (#buildAndWire faz
39
+ * build-em-locais → assign no fim). No-op quando não há `jwksLoader` (source:'jwks'
40
+ * inline ou managed sem store).
41
+ *
42
+ * Serializado por mutex (#reloadChain): chamadas concorrentes são enfileiradas em
43
+ * vez de executar em paralelo, evitando builds sobrepostos.
44
+ */
45
+ reloadKeys(): Promise<void>;
46
+ /** Idade (dias) da chave de assinatura corrente, ou null (sem keystore gerenciável). */
47
+ keystoreAgeDays(): Promise<number | null>;
48
+ /** Lista as chaves managed (kid/alg/idade/ativa), ou [] se não há keystore gerenciável. */
49
+ listManagedKeys(): Promise<ManagedKeyInfo[]>;
50
+ /**
51
+ * Rotaciona a chave de assinatura e aplica ao vivo (rotate → reloadKeys → audit
52
+ * keys.rotated). Lança quando não há keystore gerenciável. Usado pelo scheduler e
53
+ * pelo endpoint admin "rotacionar agora".
54
+ *
55
+ * Serializado por mutex (#rotateChain): chamadas concorrentes são enfileiradas para
56
+ * que duas rotações nunca se sobreponham em processo (evita perda silenciosa de escrita).
57
+ * Cada caller recebe o resultado da SUA própria rotação.
58
+ */
59
+ rotateKeys(keep: number, retire?: boolean): Promise<{
60
+ newKid: string;
61
+ retiredKids: string[];
62
+ keptKids: string[];
63
+ }>;
64
+ /**
65
+ * Invalida o cache de clients DINÂMICOS do oidc-provider (a `dynamicClients`
66
+ * QuickLRU em `instance(provider)`). DEVE ser chamado após qualquer escrita
67
+ * (create/update/delete) no model `Client` via adapter, pelo console admin.
68
+ *
69
+ * NOTA sobre o porquê: o oidc-provider v9 cacheia clients carregados do adapter
70
+ * numa LRU CUJA CHAVE É O HASH (sha256) DO PAYLOAD persistido — não o client_id.
71
+ * Por isso uma alteração de metadata já é "auto-invalidante": `Client.find` relê o
72
+ * adapter, hasheia o payload NOVO, dá cache-miss e reconstrói o client. Mesmo assim
73
+ * limpamos a LRU explicitamente para (a) tornar o efeito imediato e determinístico
74
+ * (sem depender de pressão de LRU para expulsar a entrada antiga, agora inalcançável)
75
+ * e (b) liberar a entrada órfã na hora. É o caminho de invalidação suportado: a LRU
76
+ * é um detalhe interno acessível via o helper `weak_cache` do próprio provider.
77
+ */
78
+ evictDynamicClientCache(): Promise<void>;
79
+ /** Verifica client_id + client_secret contra os clients da config (p/ endpoints custom como introspecção de PAT). */
80
+ verifyClientCredentials(clientId: string, clientSecret: string): boolean;
81
+ }
@@ -0,0 +1,254 @@
1
+ import { timingSafeEqual } from 'node:crypto';
2
+ import { NoopRecorder } from '@adonis-agora/authkit-core';
3
+ import Koa from 'koa';
4
+ import mount from 'koa-mount';
5
+ import { wireProviderEvents } from '../observability/wire_provider_events.js';
6
+ import { buildProvider } from './build_provider.js';
7
+ import { createInteractionActions } from './interaction_actions.js';
8
+ import { registerTokenExchange } from './token_exchange.js';
9
+ import { readActiveOrgFromKoaCtx } from '../host/active_org_cookie.js';
10
+ import { isFirstParty } from '../host/branding.js';
11
+ import { signingKeyAgeDays, listKeyInfos } from '../keys/keystore.js';
12
+ export class OidcService {
13
+ #provider;
14
+ #callback;
15
+ #interactions;
16
+ #appKey;
17
+ get provider() { return this.#provider; }
18
+ get callback() { return this.#callback; }
19
+ get interactions() { return this.#interactions; }
20
+ /** Pathname do issuer sem barra final (ex.: `/oidc`). Vazio quando montado na raiz. */
21
+ mountPath;
22
+ recorder;
23
+ /** Holder mutável dos TTLs de sessão OIDC (lido sincronamente pelo oidc-provider). */
24
+ sessionTtlHolder;
25
+ /** Holder mutável dos TTLs de access/id/refresh tokens (lido sincronamente pelo oidc-provider). */
26
+ tokenTtlHolder;
27
+ #clients;
28
+ #config;
29
+ /** Closures de acesso ao cofre de chaves (injetadas pelo provider para hot-reload). */
30
+ #deps;
31
+ /** Mutex de serialização de reloadKeys: encadeia execuções para nunca sobrepor builds. */
32
+ #reloadChain = Promise.resolve();
33
+ /** Mutex de serialização de rotateKeys: evita que duas rotações concorrentes se sobreponham. */
34
+ #rotateChain = Promise.resolve();
35
+ get config() {
36
+ return this.#config;
37
+ }
38
+ /** @internal Loader de JWKS do cofre (usado por reloadKeys). */
39
+ get jwksLoader() {
40
+ return this.#deps.jwksLoader;
41
+ }
42
+ /** @internal Token barato de mudança do cofre (usado pelo poll de reload). */
43
+ get keystoreHead() {
44
+ return this.#deps.keystoreHead;
45
+ }
46
+ constructor(config, appKey, recorder = new NoopRecorder(), deps = {}) {
47
+ this.#config = config;
48
+ this.#clients = config.clients ?? [];
49
+ this.#appKey = appKey;
50
+ this.recorder = recorder;
51
+ this.#deps = deps;
52
+ // Inicializa o holder de TTL com os valores do config estático.
53
+ // Será atualizado em runtime quando a setting `session_policy` for salva/apagada.
54
+ const configSessionSec = config.ttl.session;
55
+ this.sessionTtlHolder = {
56
+ rememberSec: Math.max(1, configSessionSec),
57
+ transientSec: Math.max(1, configSessionSec),
58
+ };
59
+ // Inicializa o holder de TTL de tokens com os valores do config estático.
60
+ // Será atualizado em runtime quando a setting `token_ttl` for salva/apagada.
61
+ this.tokenTtlHolder = {
62
+ accessTokenSec: Math.max(1, config.ttl.accessToken),
63
+ idTokenSec: Math.max(1, config.ttl.idToken),
64
+ refreshTokenSec: Math.max(1, config.ttl.refreshToken),
65
+ };
66
+ // mountPath é estável (o issuer nunca muda): deriva diretamente de config.issuer
67
+ // para que #buildAndWire possa ser chamado sem precisar reconstituir o mountPath.
68
+ this.mountPath = new URL(config.issuer).pathname.replace(/\/+$/, '');
69
+ this.#buildAndWire(config.jwks);
70
+ }
71
+ #buildAndWire(jwks) {
72
+ const config = this.#config;
73
+ const provider = buildProvider({ ...config, jwks }, {
74
+ appKey: this.#appKey,
75
+ findAccount: async (ctx, sub) => {
76
+ const user = await config.findAccount(sub);
77
+ if (!user)
78
+ return undefined;
79
+ // Lê a org ativa do cookie de sessão (se organizations estiver disponível).
80
+ const activeOrg = readActiveOrgFromKoaCtx(ctx);
81
+ // GATE de least-privilege: roles globais e claims de org só são emitidas para
82
+ // clients FIRST-PARTY (`branding.firstParty`). Capturamos o clientId aqui (fora
83
+ // do closure `claims()`, pois o `ctx` da request vive neste escopo). Um client
84
+ // third-party NUNCA recebe roles/org — mesmo solicitando `scope=roles`.
85
+ const clientId = ctx?.oidc?.client?.clientId;
86
+ const firstParty = config.branding
87
+ ? isFirstParty(config.branding, clientId)
88
+ : false;
89
+ return {
90
+ accountId: user.id,
91
+ claims: async (_use, _scope) => {
92
+ const base = {
93
+ sub: user.id,
94
+ email: user.email,
95
+ email_verified: true,
96
+ name: user.name,
97
+ picture: user.avatarUrl,
98
+ };
99
+ // roles/org_* são dados de autorização interna: só para first-party.
100
+ if (firstParty) {
101
+ base[config.globalRolesClaim] = user.globalRoles ?? [];
102
+ // Emite claims de org somente quando há uma org ativa na sessão.
103
+ if (activeOrg) {
104
+ base['org_id'] = activeOrg.orgId;
105
+ base['org_slug'] = activeOrg.orgSlug;
106
+ base['org_role'] = activeOrg.orgRole;
107
+ }
108
+ }
109
+ return base;
110
+ },
111
+ };
112
+ },
113
+ }, this.sessionTtlHolder, this.tokenTtlHolder);
114
+ wireProviderEvents(provider, this.recorder);
115
+ registerTokenExchange(provider, {
116
+ findAccount: config.findAccount,
117
+ globalRolesClaim: config.globalRolesClaim,
118
+ // Resource indicators (RFC 8707) suportados: o `audience` default + cada
119
+ // resource declarado. Usado para validar `audience`/`resource` no pedido de
120
+ // token-exchange — alvos fora desta lista são rejeitados (invalid_target).
121
+ supportedResources: [
122
+ config.accessTokens.audience,
123
+ ...Object.keys(config.accessTokens.resources),
124
+ ],
125
+ audit: config.audit,
126
+ });
127
+ // Quando o issuer tem um path (ex.: http://host/oidc), o provider precisa ser
128
+ // MONTADO sob esse path via koa-mount. Isso faz o oidc-provider gerar URLs de
129
+ // discovery e redirects de resume/interaction CORRETAMENTE prefixados (ex.:
130
+ // /oidc/auth, /oidc/jwks). Apenas remover o prefixo de req.url (abordagem antiga)
131
+ // fazia o provider se enxergar na raiz e anunciar URLs sem o /oidc.
132
+ // Para issuer na raiz, o mountPath é vazio e usamos o callback Node direto.
133
+ let callback;
134
+ if (this.mountPath && this.mountPath !== '/') {
135
+ const koa = new Koa();
136
+ // O app externo PRECISA herdar as Keygrip keys do provider. Sob koa-mount as
137
+ // requisições do provider rodam no contexto do app EXTERNO, então `ctx.cookies`
138
+ // usa as keys deste app. Sem isso, os cookies (_interaction, _session) seriam
139
+ // assinados/lidos de forma inconsistente entre o fluxo via mount (authorize) e as
140
+ // chamadas diretas `interactionDetails`/`interactionFinished` (que usam o contexto
141
+ // do provider), quebrando o "interaction session id cookie not found".
142
+ koa.keys = provider.keys;
143
+ koa.proxy = provider.proxy;
144
+ koa.use(mount(this.mountPath, provider));
145
+ callback = koa.callback();
146
+ }
147
+ else {
148
+ callback = provider.callback();
149
+ }
150
+ const interactions = createInteractionActions(provider, { verifyCredentials: config.verifyCredentials });
151
+ // Atribuição atômica no final: um throw antes deste ponto não corrompe o estado.
152
+ this.#provider = provider;
153
+ this.#callback = callback;
154
+ this.#interactions = interactions;
155
+ }
156
+ /**
157
+ * Recarrega as chaves de assinatura AO VIVO: relê o keystore do cofre e reconstrói
158
+ * o provider com o JWKS novo, trocando a instância atomicamente (#buildAndWire faz
159
+ * build-em-locais → assign no fim). No-op quando não há `jwksLoader` (source:'jwks'
160
+ * inline ou managed sem store).
161
+ *
162
+ * Serializado por mutex (#reloadChain): chamadas concorrentes são enfileiradas em
163
+ * vez de executar em paralelo, evitando builds sobrepostos.
164
+ */
165
+ async reloadKeys() {
166
+ const run = async () => {
167
+ const loader = this.#deps.jwksLoader;
168
+ if (!loader)
169
+ return;
170
+ const jwks = await loader();
171
+ this.#buildAndWire(jwks);
172
+ };
173
+ this.#reloadChain = this.#reloadChain.then(run, run);
174
+ return this.#reloadChain;
175
+ }
176
+ /** Idade (dias) da chave de assinatura corrente, ou null (sem keystore gerenciável). */
177
+ async keystoreAgeDays() {
178
+ const build = this.#deps.keystoreManager;
179
+ if (!build)
180
+ return null;
181
+ const m = await build();
182
+ return signingKeyAgeDays(await m.read());
183
+ }
184
+ /** Lista as chaves managed (kid/alg/idade/ativa), ou [] se não há keystore gerenciável. */
185
+ async listManagedKeys() {
186
+ const build = this.#deps.keystoreManager;
187
+ if (!build)
188
+ return [];
189
+ const m = await build();
190
+ return listKeyInfos(await m.read());
191
+ }
192
+ /**
193
+ * Rotaciona a chave de assinatura e aplica ao vivo (rotate → reloadKeys → audit
194
+ * keys.rotated). Lança quando não há keystore gerenciável. Usado pelo scheduler e
195
+ * pelo endpoint admin "rotacionar agora".
196
+ *
197
+ * Serializado por mutex (#rotateChain): chamadas concorrentes são enfileiradas para
198
+ * que duas rotações nunca se sobreponham em processo (evita perda silenciosa de escrita).
199
+ * Cada caller recebe o resultado da SUA própria rotação.
200
+ */
201
+ async rotateKeys(keep, retire = false) {
202
+ const run = async () => {
203
+ const build = this.#deps.keystoreManager;
204
+ if (!build)
205
+ throw new Error('AuthKit: rotação indisponível (jwks não é managed+store).');
206
+ const m = await build();
207
+ const { newKid, retiredKids, store } = await m.rotate(keep, retire);
208
+ await this.reloadKeys();
209
+ const keptKids = store.keys.map((k) => k.kid);
210
+ await this.#config.audit?.record({ type: 'keys.rotated', metadata: { newKid, retiredKids, keptKids, retire } }).catch(() => { });
211
+ return { newKid, retiredKids, keptKids };
212
+ };
213
+ // serializa: encadeia após a rotação em voo; cada caller recebe o resultado da SUA rotação
214
+ const result = this.#rotateChain.then(run, run);
215
+ this.#rotateChain = result.catch(() => { }); // a cadeia segue mesmo se uma rotação falhar
216
+ return result;
217
+ }
218
+ /**
219
+ * Invalida o cache de clients DINÂMICOS do oidc-provider (a `dynamicClients`
220
+ * QuickLRU em `instance(provider)`). DEVE ser chamado após qualquer escrita
221
+ * (create/update/delete) no model `Client` via adapter, pelo console admin.
222
+ *
223
+ * NOTA sobre o porquê: o oidc-provider v9 cacheia clients carregados do adapter
224
+ * numa LRU CUJA CHAVE É O HASH (sha256) DO PAYLOAD persistido — não o client_id.
225
+ * Por isso uma alteração de metadata já é "auto-invalidante": `Client.find` relê o
226
+ * adapter, hasheia o payload NOVO, dá cache-miss e reconstrói o client. Mesmo assim
227
+ * limpamos a LRU explicitamente para (a) tornar o efeito imediato e determinístico
228
+ * (sem depender de pressão de LRU para expulsar a entrada antiga, agora inalcançável)
229
+ * e (b) liberar a entrada órfã na hora. É o caminho de invalidação suportado: a LRU
230
+ * é um detalhe interno acessível via o helper `weak_cache` do próprio provider.
231
+ */
232
+ async evictDynamicClientCache() {
233
+ try {
234
+ const wc = await import('oidc-provider/lib/helpers/weak_cache.js');
235
+ const get = wc.default ?? wc.get;
236
+ const int = get(this.provider);
237
+ int?.dynamicClients?.clear?.();
238
+ }
239
+ catch {
240
+ // Estrutura interna mudou numa versão futura do oidc-provider: a invalidação por
241
+ // hash-de-conteúdo (acima) continua garantindo correção; só perdemos a expulsão
242
+ // imediata da entrada órfã. Best-effort — não propaga erro pro caminho da request.
243
+ }
244
+ }
245
+ /** Verifica client_id + client_secret contra os clients da config (p/ endpoints custom como introspecção de PAT). */
246
+ verifyClientCredentials(clientId, clientSecret) {
247
+ const client = this.#clients.find((c) => c.clientId === clientId);
248
+ if (!client || !client.clientSecret)
249
+ return false;
250
+ const a = Buffer.from(client.clientSecret);
251
+ const b = Buffer.from(clientSecret);
252
+ return a.length === b.length && timingSafeEqual(a, b);
253
+ }
254
+ }
@@ -0,0 +1,18 @@
1
+ /** Service do `@adonisjs/lock` (any de propósito — peer opt-in). */
2
+ type LockService = any;
3
+ /**
4
+ * Cria um executor single-flight: roda `fn` SÓ se conseguir o lock de imediato
5
+ * (sem esperar) — garante que apenas UMA instância execute a rotação agendada.
6
+ * Sem `@adonisjs/lock` instalado, assume single-instance e roda `fn` direto
7
+ * (no-lock). Mirror do padrão peer-lazy (limiter/drive). Libera no `finally`.
8
+ */
9
+ export interface SingleFlightOptions {
10
+ key: string;
11
+ ttlMs: number;
12
+ /** Carrega o service do lock (default: import lazy de `@adonisjs/lock/services/main`). */
13
+ loadLock?: () => Promise<LockService | null>;
14
+ /** Store do lock (db/redis); default deixa o service usar o default do host. */
15
+ store?: string;
16
+ }
17
+ export declare function makeSingleFlightLock(opts: SingleFlightOptions): (fn: () => Promise<void>) => Promise<void>;
18
+ export {};
@@ -0,0 +1,31 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ async function defaultLoadLock() {
10
+ const spec = '@adonisjs/lock/services/main';
11
+ return import(__rewriteRelativeImportExtension(spec))
12
+ .then((m) => m.default ?? null)
13
+ .catch(() => null);
14
+ }
15
+ export function makeSingleFlightLock(opts) {
16
+ const load = opts.loadLock ?? defaultLoadLock;
17
+ return async (fn) => {
18
+ const svc = await load();
19
+ if (!svc)
20
+ return fn(); // no-lock (single-instance)
21
+ const lock = (opts.store ? svc.use(opts.store) : svc.use()).createLock(opts.key, opts.ttlMs);
22
+ if (!(await lock.acquireImmediately()))
23
+ return; // outra instância tem o lock
24
+ try {
25
+ await fn();
26
+ }
27
+ finally {
28
+ await lock.release().catch(() => { });
29
+ }
30
+ };
31
+ }
@@ -0,0 +1,21 @@
1
+ import type { AuditSink } from '../audit/audit_sink.js';
2
+ export interface TokenExchangeAccount {
3
+ id: string;
4
+ email?: string;
5
+ name?: string;
6
+ globalRoles?: string[];
7
+ }
8
+ export interface TokenExchangeDeps {
9
+ findAccount: (sub: string) => Promise<TokenExchangeAccount | null>;
10
+ globalRolesClaim: string;
11
+ adminRole?: string;
12
+ /**
13
+ * Resource indicators (RFC 8707) suportados pelo provider. Quando o pedido traz
14
+ * `audience`/`resource`, validamos contra esta lista; um alvo não suportado é
15
+ * rejeitado (conservador). Vazio/ausente => nenhum resource é aceito no pedido.
16
+ */
17
+ supportedResources?: string[];
18
+ /** Sink de auditoria (best-effort). Quando presente, registra `impersonation`. */
19
+ audit?: AuditSink;
20
+ }
21
+ export declare function registerTokenExchange(provider: any, deps: TokenExchangeDeps): void;
@@ -0,0 +1,124 @@
1
+ import { errors } from 'oidc-provider';
2
+ const TOKEN_EXCHANGE = 'urn:ietf:params:oauth:grant-type:token-exchange';
3
+ const ACCESS_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token';
4
+ /**
5
+ * Interseção entre os scopes pedidos e os scopes permitidos do client (allowlist).
6
+ * Preserva a ordem do pedido. Nunca excede a allowlist do client.
7
+ */
8
+ function intersectScopes(requested, allowed) {
9
+ const out = [];
10
+ for (const s of requested.split(' ')) {
11
+ const t = s.trim();
12
+ if (t && allowed.has(t) && !out.includes(t))
13
+ out.push(t);
14
+ }
15
+ return out.join(' ');
16
+ }
17
+ export function registerTokenExchange(provider, deps) {
18
+ const adminRole = deps.adminRole ?? 'ADMIN';
19
+ const supportedResources = new Set(deps.supportedResources ?? []);
20
+ const handler = async (ctx) => {
21
+ const { params, client } = ctx.oidc;
22
+ if (params.subject_token_type !== ACCESS_TOKEN_TYPE) {
23
+ throw new errors.InvalidRequest('unsupported subject_token_type');
24
+ }
25
+ if (!params.subject_token) {
26
+ throw new errors.InvalidRequest('subject_token is required');
27
+ }
28
+ const subjectAt = await provider.AccessToken.find(params.subject_token);
29
+ if (!subjectAt || subjectAt.isExpired) {
30
+ throw new errors.InvalidGrant('subject_token invalid or expired');
31
+ }
32
+ // O subject_token DEVE ter sido emitido para o MESMO client autenticado: senão
33
+ // um client B poderia trocar um AT emitido para o client A (cross-client).
34
+ if (subjectAt.clientId !== client?.clientId) {
35
+ throw new errors.InvalidGrant('subject_token was not issued to this client');
36
+ }
37
+ const actor = await deps.findAccount(subjectAt.accountId);
38
+ if (!actor || !(actor.globalRoles ?? []).includes(adminRole)) {
39
+ throw new errors.InvalidGrant('actor not permitted to impersonate');
40
+ }
41
+ const targetId = params.requested_subject;
42
+ if (!targetId) {
43
+ throw new errors.InvalidRequest('requested_subject is required');
44
+ }
45
+ const target = await deps.findAccount(targetId);
46
+ if (!target) {
47
+ throw new errors.InvalidGrant('requested_subject not found');
48
+ }
49
+ // audience/resource: se o pedido vier com um alvo, ele PRECISA estar entre os
50
+ // resource indicators suportados. Caso contrário rejeitamos (conservador) —
51
+ // nunca embutimos audiência arbitrária no token emitido.
52
+ const requestedTargets = [params.audience, params.resource].filter((v) => typeof v === 'string' && v.length > 0);
53
+ for (const tgt of requestedTargets) {
54
+ if (!supportedResources.has(tgt)) {
55
+ throw new errors.InvalidTarget('requested audience/resource is not supported');
56
+ }
57
+ }
58
+ // scope: nunca exceder os scopes permitidos do client autenticado. Quando o
59
+ // client DECLARA `scope` (allowlist), o pedido é reduzido à INTERSEÇÃO com ela.
60
+ // Quando o client NÃO declara `scope` (metadata ausente nesta lib = "não
61
+ // configurado", não "nenhum scope"), preservamos o comportamento atual: usa o
62
+ // `scope` pedido, ou o default mínimo se o pedido vier vazio.
63
+ const clientScopes = new Set(String(client?.scope ?? '')
64
+ .split(' ')
65
+ .map((s) => s.trim())
66
+ .filter(Boolean));
67
+ const DEFAULT_SCOPE = 'openid profile email';
68
+ let scope;
69
+ if (clientScopes.size) {
70
+ // Client com allowlist explícita: interseção (pedido) ou a própria allowlist.
71
+ scope = params.scope
72
+ ? intersectScopes(params.scope, clientScopes)
73
+ : [...clientScopes].join(' ');
74
+ // Pedido explícito sem nenhuma interseção → erro claro, não token de scope vazio.
75
+ if (params.scope && !scope) {
76
+ throw new errors.InvalidScope('requested scope is not allowed for this client', params.scope);
77
+ }
78
+ }
79
+ else {
80
+ // Client sem allowlist declarada: comportamento atual preservado.
81
+ scope = params.scope || DEFAULT_SCOPE;
82
+ }
83
+ const at = new provider.AccessToken({ accountId: target.id, client, scope });
84
+ const accessToken = await at.save();
85
+ const idToken = new provider.IdToken({
86
+ sub: target.id,
87
+ email: target.email,
88
+ email_verified: true,
89
+ name: target.name,
90
+ [deps.globalRolesClaim]: target.globalRoles ?? [],
91
+ }, { ctx });
92
+ idToken.scope = scope;
93
+ idToken.set('act', { sub: actor.id });
94
+ const idTokenJwt = await idToken.issue({ use: 'idtoken' });
95
+ await deps.audit?.record({
96
+ type: 'impersonation',
97
+ actorId: actor.id,
98
+ accountId: target.id,
99
+ email: target.email ?? null,
100
+ clientId: client?.clientId ?? null,
101
+ ip: ctx.req?.socket?.remoteAddress ?? null,
102
+ metadata: { scope },
103
+ });
104
+ ctx.body = {
105
+ access_token: accessToken,
106
+ issued_token_type: ACCESS_TOKEN_TYPE,
107
+ token_type: at.tokenType ?? 'Bearer',
108
+ expires_in: at.expiration ?? 3600,
109
+ id_token: idTokenJwt,
110
+ scope,
111
+ };
112
+ };
113
+ provider.registerGrantType(TOKEN_EXCHANGE, handler, [
114
+ 'subject_token',
115
+ 'subject_token_type',
116
+ 'requested_subject',
117
+ 'requested_token_type',
118
+ 'scope',
119
+ 'audience',
120
+ 'resource',
121
+ 'actor_token',
122
+ 'actor_token_type',
123
+ ], ['audience', 'resource']);
124
+ }
@@ -0,0 +1,16 @@
1
+ import type { Router } from '@adonisjs/core/http';
2
+ /**
3
+ * Registra a rota catch-all que delega ao handler do oidc-provider.
4
+ * O issuer do consumidor deve terminar em `mountPath` (default `/oidc`),
5
+ * pois o oidc-provider roteia internamente sob o issuer.
6
+ * Uso: registerOidcRoutes(router) no start/routes.ts do auth-service.
7
+ *
8
+ * Observabilidade (opt-in):
9
+ * - `metrics: true` monta `GET /authkit/metrics` (snapshot JSON).
10
+ * - `dashboard: true` monta `GET /authkit/dashboard` (HTML embutido).
11
+ */
12
+ export declare function registerOidcRoutes(router: Router, options?: {
13
+ mountPath?: string;
14
+ metrics?: boolean;
15
+ dashboard?: boolean;
16
+ }): void;
@@ -0,0 +1,21 @@
1
+ import OidcCallbackController from './controllers/oidc_callback_controller.js';
2
+ import MetricsController from './observability/metrics_controller.js';
3
+ /**
4
+ * Registra a rota catch-all que delega ao handler do oidc-provider.
5
+ * O issuer do consumidor deve terminar em `mountPath` (default `/oidc`),
6
+ * pois o oidc-provider roteia internamente sob o issuer.
7
+ * Uso: registerOidcRoutes(router) no start/routes.ts do auth-service.
8
+ *
9
+ * Observabilidade (opt-in):
10
+ * - `metrics: true` monta `GET /authkit/metrics` (snapshot JSON).
11
+ * - `dashboard: true` monta `GET /authkit/dashboard` (HTML embutido).
12
+ */
13
+ export function registerOidcRoutes(router, options = {}) {
14
+ const mount = options.mountPath ?? '/oidc';
15
+ router.any(`${mount}/*`, [OidcCallbackController]).as('authkit.oidc.wildcard');
16
+ router.any(mount, [OidcCallbackController]).as('authkit.oidc.root');
17
+ if (options.metrics)
18
+ router.get('/authkit/metrics', [MetricsController, 'json']);
19
+ if (options.dashboard)
20
+ router.get('/authkit/dashboard', [MetricsController, 'dashboard']);
21
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Schema das tabelas que o PRÓPRIO authkit possui (nomes fixos). As tabelas
3
+ * do host (users, webauthn credentials, provider identities, PATs, audit)
4
+ * ficam de fora de propósito: nome e shape são decisão do host.
5
+ *
6
+ * `ensureAuthkitSchema()` é ADITIVO e idempotente:
7
+ * - cria as tabelas que faltam;
8
+ * - adiciona colunas novas em tabelas existentes (ALTER ADD);
9
+ * - nunca dropa nada nem altera tipo de coluna existente.
10
+ *
11
+ * Roda automaticamente no boot quando `schema.autoManage` está ligado
12
+ * (default), ou manualmente dentro de uma migration do host:
13
+ *
14
+ * ```ts
15
+ * // database/migrations/xxxx_authkit_schema.ts
16
+ * import { BaseSchema } from '@adonisjs/lucid/schema'
17
+ * import { ensureAuthkitSchema } from '@adonis-agora/authkit-server'
18
+ *
19
+ * export default class extends BaseSchema {
20
+ * async up() {
21
+ * await ensureAuthkitSchema(this.db)
22
+ * }
23
+ * }
24
+ * ```
25
+ */
26
+ export interface EnsureSchemaOptions {
27
+ /** Conexão Lucid a usar. Default: conexão primária. */
28
+ connection?: string;
29
+ }
30
+ export interface EnsureSchemaReport {
31
+ /** Tabelas criadas do zero nesta execução. */
32
+ created: string[];
33
+ /** Colunas adicionadas em tabelas já existentes: tabela → colunas. */
34
+ altered: Record<string, string[]>;
35
+ }
36
+ /**
37
+ * Garante que as tabelas do authkit existem e têm todas as colunas que esta
38
+ * versão da lib espera. Aditivo e idempotente — seguro de rodar em todo boot
39
+ * e dentro de migrations.
40
+ */
41
+ export declare function ensureAuthkitSchema(db: any, options?: EnsureSchemaOptions): Promise<EnsureSchemaReport>;