@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,22 @@
1
+ import type { HttpContext } from '@adonisjs/core/http';
2
+ export default class PatIntrospectionController {
3
+ handle(ctx: HttpContext): Promise<void | {
4
+ active: boolean;
5
+ sub?: undefined;
6
+ email?: undefined;
7
+ name?: undefined;
8
+ roles?: undefined;
9
+ scopes?: undefined;
10
+ audience?: undefined;
11
+ exp?: undefined;
12
+ } | {
13
+ active: boolean;
14
+ sub: any;
15
+ email: any;
16
+ name: any;
17
+ roles: any;
18
+ scopes: any;
19
+ audience: any;
20
+ exp: any;
21
+ }>;
22
+ }
@@ -0,0 +1,46 @@
1
+ import { timingSafeEqual } from 'node:crypto';
2
+ function bearerMatches(header, expected) {
3
+ if (!header || !header.startsWith('Bearer '))
4
+ return false;
5
+ const provided = header.slice(7);
6
+ const a = Buffer.from(provided);
7
+ const b = Buffer.from(expected);
8
+ return a.length === b.length && timingSafeEqual(a, b);
9
+ }
10
+ export default class PatIntrospectionController {
11
+ async handle(ctx) {
12
+ const service = await ctx.containerResolver.make('authkit.server');
13
+ const cfg = service.config;
14
+ const secret = cfg.patIntrospectionSecret;
15
+ if (!secret || !bearerMatches(ctx.request.header('authorization'), secret)) {
16
+ return ctx.response.unauthorized({ error: 'invalid_client' });
17
+ }
18
+ const token = ctx.request.input('token');
19
+ if (!token || typeof token !== 'string') {
20
+ return { active: false };
21
+ }
22
+ const meta = await cfg.patStore.findActiveByToken(token);
23
+ if (!meta)
24
+ return { active: false };
25
+ const account = await cfg.accountStore.findById(meta.accountId);
26
+ if (!account)
27
+ return { active: false };
28
+ await cfg.audit?.record({
29
+ type: 'pat.used',
30
+ accountId: account.id,
31
+ email: account.email,
32
+ ip: ctx.request.ip?.() ?? null,
33
+ metadata: { audience: meta.audience },
34
+ });
35
+ return {
36
+ active: true,
37
+ sub: account.id,
38
+ email: account.email,
39
+ name: account.name ?? null,
40
+ roles: account.globalRoles ?? [],
41
+ scopes: meta.scopes,
42
+ audience: meta.audience,
43
+ exp: meta.exp,
44
+ };
45
+ }
46
+ }
@@ -0,0 +1,18 @@
1
+ import '../augmentations.js';
2
+ import type { HttpContext } from '@adonisjs/core/http';
3
+ export default class AuthRegistrationController {
4
+ /** GET /auth/interaction/:uid/signup — tela de cadastro (dentro do fluxo OIDC). */
5
+ showSignup(ctx: HttpContext): Promise<any>;
6
+ /** POST /auth/interaction/:uid/signup — cria o usuário e finaliza o login. */
7
+ signup(ctx: HttpContext): Promise<any>;
8
+ /** GET /auth/forgot-password — tela standalone. */
9
+ showForgot(ctx: HttpContext): Promise<any>;
10
+ /** POST /auth/forgot-password — gera token e (dev) loga o link. Sempre responde sucesso (não vaza emails). */
11
+ forgot(ctx: HttpContext): Promise<any>;
12
+ /** GET /auth/reset-password?token=... — tela standalone. */
13
+ showReset(ctx: HttpContext): Promise<any>;
14
+ /** POST /auth/reset-password — redefine a senha. */
15
+ reset(ctx: HttpContext): Promise<any>;
16
+ /** GET /auth/verify-email?token=... — consome o token e mostra sucesso/falha. */
17
+ verifyEmail(ctx: HttpContext): Promise<any>;
18
+ }
@@ -0,0 +1,382 @@
1
+ import '../augmentations.js';
2
+ import { brandFor } from '../branding.js';
3
+ import { signupValidator, forgotPasswordValidator, resetPasswordValidator } from '../validators.js';
4
+ import { sendPasswordResetEmail, sendEmailVerificationEmail } from '../default_mailer.js';
5
+ import { translate } from '../i18n.js';
6
+ import { PasswordPolicyError } from '../../password/password_manager.js';
7
+ import { guardBotProtection, resolveEffectiveBotProtection } from '../bot_protection.js';
8
+ import { RuntimeSettings, resolveRuntimeSettings } from '../runtime_settings.js';
9
+ import { resolveEffectiveRegistration, resolveEffectiveMaintenanceMode, resolveEffectiveAuthMethods, } from '../runtime_toggles.js';
10
+ import { dispatchSecurityNotice } from '../security_notice_service.js';
11
+ import { AdminSessionsService } from '../admin_sessions_service.js';
12
+ /**
13
+ * Best-effort: returns a RuntimeSettings backed by the container DB, or a no-op
14
+ * fallback. Contrato NON-NULL preservado (callers passam direto p/ resolvers que
15
+ * exigem SettingsCapability). Reusa a fábrica canônica `resolveRuntimeSettings`
16
+ * e degrada para o RuntimeSettings no-op (probe via SELECT lança → tabela ausente
17
+ * → config fallback) quando a resolução falha.
18
+ */
19
+ async function getRuntimeSettings(ctx) {
20
+ const rs = await resolveRuntimeSettings(ctx);
21
+ return rs ?? new RuntimeSettings({ table: () => { throw new Error('no-op'); } });
22
+ }
23
+ export default class AuthRegistrationController {
24
+ /** GET /auth/interaction/:uid/signup — tela de cadastro (dentro do fluxo OIDC). */
25
+ async showSignup(ctx) {
26
+ const service = await ctx.containerResolver.make('authkit.server');
27
+ const cfg = service.config;
28
+ const render = cfg.render;
29
+ const details = await service.interactions.details(ctx);
30
+ const brand = brandFor(cfg.branding, details.params.client_id);
31
+ const runtimeSettings = await getRuntimeSettings(ctx);
32
+ // Maintenance mode: mostra página de manutenção se ativo.
33
+ const maintenance = await resolveEffectiveMaintenanceMode(runtimeSettings);
34
+ if (maintenance.enabled) {
35
+ return render(ctx, 'maintenance', {
36
+ csrfToken: ctx.request.csrfToken,
37
+ message: maintenance.message ?? translate(cfg.messages, 'maintenance.default_message'),
38
+ brand,
39
+ });
40
+ }
41
+ // Registration disabled: mostra mensagem clara na tela de signup.
42
+ const registrationEnabled = await resolveEffectiveRegistration(cfg.registration?.enabled ?? true, runtimeSettings);
43
+ if (!registrationEnabled) {
44
+ return render(ctx, 'signup', {
45
+ uid: details.uid,
46
+ csrfToken: ctx.request.csrfToken,
47
+ brand,
48
+ registrationDisabled: true,
49
+ registrationDisabledMessage: translate(cfg.messages, 'errors.registration_disabled'),
50
+ });
51
+ }
52
+ const effectiveBot = await resolveEffectiveBotProtection(cfg.botProtection, runtimeSettings);
53
+ return render(ctx, 'signup', {
54
+ uid: details.uid,
55
+ csrfToken: ctx.request.csrfToken,
56
+ brand,
57
+ botProtection: effectiveBot?.on.includes('signup') ? effectiveBot.widget : undefined,
58
+ });
59
+ }
60
+ /** POST /auth/interaction/:uid/signup — cria o usuário e finaliza o login. */
61
+ async signup(ctx) {
62
+ const service = await ctx.containerResolver.make('authkit.server');
63
+ const cfg = service.config;
64
+ const render = cfg.render;
65
+ const details = await service.interactions.details(ctx);
66
+ const brand = brandFor(cfg.branding, details.params.client_id);
67
+ const runtimeSettings = await getRuntimeSettings(ctx);
68
+ // Maintenance mode: rejeita o POST durante manutenção.
69
+ const maintenance = await resolveEffectiveMaintenanceMode(runtimeSettings);
70
+ if (maintenance.enabled) {
71
+ return render(ctx, 'maintenance', {
72
+ csrfToken: ctx.request.csrfToken,
73
+ message: maintenance.message ?? translate(cfg.messages, 'maintenance.default_message'),
74
+ brand,
75
+ });
76
+ }
77
+ // Registration disabled: rejeita o POST — mesmo que alguém bata diretamente.
78
+ const registrationEnabled = await resolveEffectiveRegistration(cfg.registration?.enabled ?? true, runtimeSettings);
79
+ if (!registrationEnabled) {
80
+ return render(ctx, 'signup', {
81
+ uid: ctx.request.param('uid'),
82
+ csrfToken: ctx.request.csrfToken,
83
+ brand,
84
+ registrationDisabled: true,
85
+ registrationDisabledMessage: translate(cfg.messages, 'errors.registration_disabled'),
86
+ });
87
+ }
88
+ // Effective bot protection: may be overridden at runtime via auth_settings.
89
+ const effectiveBotSignup = await resolveEffectiveBotProtection(cfg.botProtection, runtimeSettings);
90
+ const cfgWithEffectiveBotSignup = effectiveBotSignup !== cfg.botProtection
91
+ ? { ...cfg, botProtection: effectiveBotSignup }
92
+ : cfg;
93
+ // Bot protection (plugável): valida o token do widget ANTES de criar a conta.
94
+ // Fail-safe: erro/timeout no verify do host PERMITE o cadastro.
95
+ const clientId = details.params.client_id ?? null;
96
+ if (!(await guardBotProtection(ctx, cfgWithEffectiveBotSignup, 'signup', { clientId }))) {
97
+ return render(ctx, 'signup', {
98
+ uid: ctx.request.param('uid'),
99
+ csrfToken: ctx.request.csrfToken,
100
+ error: translate(cfg.messages, 'errors.bot_protection_failed'),
101
+ brand,
102
+ botProtection: effectiveBotSignup?.widget,
103
+ });
104
+ }
105
+ const data = await ctx.request.validateUsing(signupValidator);
106
+ const accountStore = cfg.accountStore;
107
+ const existing = await accountStore.findByEmail(data.email);
108
+ if (existing) {
109
+ return render(ctx, 'signup', {
110
+ uid: ctx.request.param('uid'),
111
+ csrfToken: ctx.request.csrfToken,
112
+ error: translate(cfg.messages, 'errors.email_taken'),
113
+ brand,
114
+ botProtection: effectiveBotSignup?.on.includes('signup') ? effectiveBotSignup.widget : undefined,
115
+ });
116
+ }
117
+ let created;
118
+ try {
119
+ created = await accountStore.create({
120
+ email: data.email,
121
+ password: data.password,
122
+ fullName: data.fullName,
123
+ });
124
+ }
125
+ catch (error) {
126
+ // Política de senha (comprimento/complexidade/vazamento) violada → re-renderiza
127
+ // com a mensagem i18n específica da regra.
128
+ if (error instanceof PasswordPolicyError) {
129
+ return render(ctx, 'signup', {
130
+ uid: ctx.request.param('uid'),
131
+ csrfToken: ctx.request.csrfToken,
132
+ error: translate(cfg.messages, error.key, error.params),
133
+ brand,
134
+ botProtection: effectiveBotSignup?.on.includes('signup') ? effectiveBotSignup.widget : undefined,
135
+ });
136
+ }
137
+ throw error;
138
+ }
139
+ await cfg.audit?.record({
140
+ type: 'signup',
141
+ accountId: created?.id ?? null,
142
+ email: data.email,
143
+ ip: ctx.request.ip?.() ?? null,
144
+ clientId: details.params.client_id ?? null,
145
+ });
146
+ // Finaliza a interaction como login (interactionFinished escreve o redirect 303 que
147
+ // retoma o authorize; o form nativo da tela segue esse redirect no sucesso).
148
+ const result = await service.interactions.login(ctx, {
149
+ email: data.email,
150
+ password: data.password,
151
+ });
152
+ if (!result.ok) {
153
+ return render(ctx, 'signup', {
154
+ uid: ctx.request.param('uid'),
155
+ csrfToken: ctx.request.csrfToken,
156
+ error: translate(cfg.messages, 'errors.signup_failed'),
157
+ brand,
158
+ botProtection: effectiveBotSignup?.on.includes('signup') ? effectiveBotSignup.widget : undefined,
159
+ });
160
+ }
161
+ // Verificação de e-mail (best-effort — não bloqueia nem reverte o login).
162
+ try {
163
+ const issued = await accountStore.issueEmailVerificationToken(data.email);
164
+ if (issued) {
165
+ await cfg.audit?.record({
166
+ type: 'email_verification.issued',
167
+ accountId: created?.id ?? null,
168
+ email: data.email,
169
+ ip: ctx.request.ip?.() ?? null,
170
+ });
171
+ const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
172
+ const verifyUrl = `${origin}/auth/verify-email?token=${issued.token}`;
173
+ // Hook do config tem prioridade (override); senão usa o mailer default do host.
174
+ if (cfg.mail?.onEmailVerification) {
175
+ await cfg.mail.onEmailVerification({ email: data.email, verifyUrl, token: issued.token });
176
+ }
177
+ else {
178
+ await sendEmailVerificationEmail(ctx, { email: data.email, verifyUrl });
179
+ }
180
+ }
181
+ }
182
+ catch (error) {
183
+ ctx.logger.error({ err: error, email: data.email }, 'authkit: falha ao enviar verificação de e-mail');
184
+ }
185
+ }
186
+ /** GET /auth/forgot-password — tela standalone. */
187
+ async showForgot(ctx) {
188
+ const service = await ctx.containerResolver.make('authkit.server');
189
+ const cfg = service.config;
190
+ const render = cfg.render;
191
+ const runtimeSettings = await getRuntimeSettings(ctx);
192
+ // Maintenance mode: mostra página de manutenção.
193
+ const maintenance = await resolveEffectiveMaintenanceMode(runtimeSettings);
194
+ if (maintenance.enabled) {
195
+ return render(ctx, 'maintenance', {
196
+ csrfToken: ctx.request.csrfToken,
197
+ message: maintenance.message ?? translate(cfg.messages, 'maintenance.default_message'),
198
+ });
199
+ }
200
+ // auth_methods: se forgotPassword efetivo for false → 404 (endpoint desligado).
201
+ const authMethods = await resolveEffectiveAuthMethods(runtimeSettings, {
202
+ configuredSocialProviders: cfg.social?.providers ?? [],
203
+ magicLinkCapable: cfg.passwordless?.magicLink && typeof cfg.accountStore.issueMagicLinkToken === 'function',
204
+ });
205
+ if (!authMethods.forgotPassword) {
206
+ return ctx.response.notFound({ error: translate(cfg.messages, 'errors.not_found') });
207
+ }
208
+ const effectiveBot = await resolveEffectiveBotProtection(cfg.botProtection, runtimeSettings);
209
+ return render(ctx, 'forgot', {
210
+ csrfToken: ctx.request.csrfToken,
211
+ botProtection: effectiveBot?.on.includes('reset') ? effectiveBot.widget : undefined,
212
+ });
213
+ }
214
+ /** POST /auth/forgot-password — gera token e (dev) loga o link. Sempre responde sucesso (não vaza emails). */
215
+ async forgot(ctx) {
216
+ const service = await ctx.containerResolver.make('authkit.server');
217
+ const cfg = service.config;
218
+ const render = cfg.render;
219
+ const runtimeSettings = await getRuntimeSettings(ctx);
220
+ // Maintenance mode: rejeita o POST.
221
+ const maintenance = await resolveEffectiveMaintenanceMode(runtimeSettings);
222
+ if (maintenance.enabled) {
223
+ return render(ctx, 'maintenance', {
224
+ csrfToken: ctx.request.csrfToken,
225
+ message: maintenance.message ?? translate(cfg.messages, 'maintenance.default_message'),
226
+ });
227
+ }
228
+ // auth_methods: se forgotPassword efetivo for false → 404 (endpoint desligado).
229
+ const authMethods = await resolveEffectiveAuthMethods(runtimeSettings, {
230
+ configuredSocialProviders: cfg.social?.providers ?? [],
231
+ magicLinkCapable: cfg.passwordless?.magicLink && typeof cfg.accountStore.issueMagicLinkToken === 'function',
232
+ });
233
+ if (!authMethods.forgotPassword) {
234
+ return ctx.response.notFound({ error: translate(cfg.messages, 'errors.not_found') });
235
+ }
236
+ // Effective bot protection: may be overridden at runtime via auth_settings.
237
+ const effectiveBotForgot = await resolveEffectiveBotProtection(cfg.botProtection, runtimeSettings);
238
+ const cfgWithEffectiveBotForgot = effectiveBotForgot !== cfg.botProtection
239
+ ? { ...cfg, botProtection: effectiveBotForgot }
240
+ : cfg;
241
+ // Bot protection (plugável): valida o token do widget ANTES de emitir o token
242
+ // de reset. Fail-safe: erro/timeout no verify do host PERMITE o fluxo.
243
+ if (!(await guardBotProtection(ctx, cfgWithEffectiveBotForgot, 'reset'))) {
244
+ return render(ctx, 'forgot', {
245
+ csrfToken: ctx.request.csrfToken,
246
+ error: translate(cfg.messages, 'errors.bot_protection_failed'),
247
+ botProtection: effectiveBotForgot?.widget,
248
+ });
249
+ }
250
+ const { email } = await ctx.request.validateUsing(forgotPasswordValidator);
251
+ const accountStore = cfg.accountStore;
252
+ const result = await accountStore.issuePasswordResetToken(email);
253
+ if (result) {
254
+ await cfg.audit?.record({
255
+ type: 'password_reset.issued',
256
+ email,
257
+ ip: ctx.request.ip?.() ?? null,
258
+ });
259
+ const origin = `${ctx.request.protocol()}://${ctx.request.host()}`;
260
+ const url = `${origin}/auth/reset-password?token=${result.token}`;
261
+ // Hook do config tem prioridade (override); senão usa o mailer default do host.
262
+ if (cfg.mail?.onPasswordReset) {
263
+ await cfg.mail.onPasswordReset({ email, resetUrl: url, token: result.token });
264
+ }
265
+ else {
266
+ await sendPasswordResetEmail(ctx, { email, resetUrl: url });
267
+ }
268
+ }
269
+ return render(ctx, 'forgot', {
270
+ csrfToken: ctx.request.csrfToken,
271
+ sent: true,
272
+ });
273
+ }
274
+ /** GET /auth/reset-password?token=... — tela standalone. */
275
+ async showReset(ctx) {
276
+ const service = await ctx.containerResolver.make('authkit.server');
277
+ const cfg = service.config;
278
+ const render = cfg.render;
279
+ const token = ctx.request.qs().token ?? '';
280
+ return render(ctx, 'reset', { token, csrfToken: ctx.request.csrfToken });
281
+ }
282
+ /** POST /auth/reset-password — redefine a senha. */
283
+ async reset(ctx) {
284
+ const service = await ctx.containerResolver.make('authkit.server');
285
+ const cfg = service.config;
286
+ const render = cfg.render;
287
+ const { token, password } = await ctx.request.validateUsing(resetPasswordValidator);
288
+ const accountStore = cfg.accountStore;
289
+ // Pré-lookup da conta pelo token (best-effort) para a notificação de segurança.
290
+ // O token é consumido a seguir, então buscamos antes de chamar consumePasswordResetToken.
291
+ let accountForNotice;
292
+ try {
293
+ // issuePasswordResetToken coloca o token no campo passwordResetToken; podemos
294
+ // procurar pelo e-mail via store se ele suportar lookup por token (não é um
295
+ // método público). Tentamos via findByPasswordResetToken se disponível; senão
296
+ // pulamos o aviso graciosamente.
297
+ const storeAny = accountStore;
298
+ if (typeof storeAny.findByPasswordResetToken === 'function') {
299
+ accountForNotice = await storeAny.findByPasswordResetToken(token);
300
+ }
301
+ }
302
+ catch {
303
+ // Silencioso — aviso é best-effort.
304
+ }
305
+ let ok;
306
+ try {
307
+ ok = await accountStore.consumePasswordResetToken(token, password);
308
+ }
309
+ catch (error) {
310
+ // Política de senha violada → re-renderiza a tela de reset com a regra.
311
+ if (error instanceof PasswordPolicyError) {
312
+ return render(ctx, 'reset', {
313
+ token,
314
+ csrfToken: ctx.request.csrfToken,
315
+ error: translate(cfg.messages, error.key, error.params),
316
+ });
317
+ }
318
+ throw error;
319
+ }
320
+ if (!ok) {
321
+ return ctx.response.badRequest({ error: translate(cfg.messages, 'errors.invalid_or_expired_token') });
322
+ }
323
+ await cfg.audit?.record({
324
+ type: 'password_reset.consumed',
325
+ ip: ctx.request.ip?.() ?? null,
326
+ });
327
+ // M2: reset de senha INVALIDA todas as sessões/grants da conta (segurança >
328
+ // conveniência — quem reseta a senha pode estar recuperando uma conta
329
+ // comprometida). Best-effort/fail-safe: uma falha aqui NÃO falha o reset.
330
+ if (accountForNotice) {
331
+ try {
332
+ const sessions = new AdminSessionsService(service);
333
+ const result = await sessions.revokeAll(accountForNotice.id);
334
+ await cfg.audit?.record({
335
+ type: 'session.revoked_all',
336
+ accountId: accountForNotice.id,
337
+ actorId: null,
338
+ ip: ctx.request.ip?.() ?? null,
339
+ metadata: {
340
+ sessions: result.sessions,
341
+ grants: result.grants,
342
+ accessTokens: result.accessTokens,
343
+ refreshTokens: result.refreshTokens,
344
+ source: 'password-reset',
345
+ },
346
+ });
347
+ }
348
+ catch {
349
+ // fail-safe: a troca de senha já vale; a invalidação é best-effort.
350
+ }
351
+ }
352
+ // Notificação de segurança: senha alterada via reset (best-effort, fail-safe).
353
+ if (accountForNotice) {
354
+ await dispatchSecurityNotice(ctx, {
355
+ account: accountForNotice,
356
+ kind: 'password_changed',
357
+ ip: ctx.request.ip?.() ?? null,
358
+ timestamp: new Date().toISOString(),
359
+ }, cfg.mail, cfg.audit);
360
+ }
361
+ return render(ctx, 'reset', {
362
+ token: '',
363
+ csrfToken: ctx.request.csrfToken,
364
+ done: true,
365
+ });
366
+ }
367
+ /** GET /auth/verify-email?token=... — consome o token e mostra sucesso/falha. */
368
+ async verifyEmail(ctx) {
369
+ const service = await ctx.containerResolver.make('authkit.server');
370
+ const cfg = service.config;
371
+ const render = cfg.render;
372
+ const token = ctx.request.qs().token ?? '';
373
+ const ok = await cfg.accountStore.consumeEmailVerificationToken(token);
374
+ if (ok) {
375
+ await cfg.audit?.record({
376
+ type: 'email_verification.consumed',
377
+ ip: ctx.request.ip?.() ?? null,
378
+ });
379
+ }
380
+ return render(ctx, 'verify-email', { verified: ok });
381
+ }
382
+ }
@@ -0,0 +1,8 @@
1
+ import '../augmentations.js';
2
+ import type { HttpContext } from '@adonisjs/core/http';
3
+ export default class AuthSocialController {
4
+ /** GET /auth/:provider/redirect/:uid — guarda o uid e redireciona para o provider OAuth. */
5
+ redirect(ctx: HttpContext): Promise<void>;
6
+ /** GET /auth/:provider/callback — retorno do provider → acha/cria AuthUser → conclui a interaction. */
7
+ callback(ctx: HttpContext): Promise<void>;
8
+ }
@@ -0,0 +1,89 @@
1
+ import '../augmentations.js';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { supportsProviderIdentity } from '../../accounts/account_store.js';
4
+ const UID_SESSION_KEY = 'authkit_social_uid';
5
+ /**
6
+ * `AllyService.use()` é tipado contra a interface `SocialProviders`, que só é
7
+ * preenchida pelo HOST (a lib não conhece os providers configurados). Para um
8
+ * nome de provider dinâmico (vindo da rota), o retorno colapsa em `never`, então
9
+ * resolvemos via o contrato genérico do driver — sem cast pro `HttpContext` inteiro.
10
+ */
11
+ function useProvider(ctx, provider) {
12
+ return ctx.ally.use(provider);
13
+ }
14
+ export default class AuthSocialController {
15
+ /** GET /auth/:provider/redirect/:uid — guarda o uid e redireciona para o provider OAuth. */
16
+ async redirect(ctx) {
17
+ const provider = ctx.request.param('provider');
18
+ ctx.session.put(UID_SESSION_KEY, ctx.request.param('uid'));
19
+ return useProvider(ctx, provider).redirect();
20
+ }
21
+ /** GET /auth/:provider/callback — retorno do provider → acha/cria AuthUser → conclui a interaction. */
22
+ async callback(ctx) {
23
+ const provider = ctx.request.param('provider');
24
+ const social = useProvider(ctx, provider);
25
+ const uid = ctx.session.get(UID_SESSION_KEY);
26
+ const backToLogin = uid ? `/auth/interaction/${uid}` : '/health';
27
+ if (social.accessDenied() || social.stateMisMatch() || social.hasError()) {
28
+ ctx.session.forget(UID_SESSION_KEY);
29
+ return ctx.response.redirect(backToLogin);
30
+ }
31
+ const profile = await social.user();
32
+ // `profile.id` é o id estável do usuário no provider — independe do e-mail.
33
+ if (!profile.id) {
34
+ ctx.session.forget(UID_SESSION_KEY);
35
+ return ctx.response.redirect(backToLogin);
36
+ }
37
+ const service = await ctx.containerResolver.make('authkit.server');
38
+ const cfg = service.config;
39
+ const store = cfg.accountStore;
40
+ const email = profile.email ?? undefined;
41
+ // Account linking exige a capacidade de provider-identity (model wired no store).
42
+ // Ausente → não há como ligar a identidade; volta ao login em vez de quebrar.
43
+ if (!supportsProviderIdentity(store)) {
44
+ ctx.session.forget(UID_SESSION_KEY);
45
+ return ctx.response.redirect(backToLogin);
46
+ }
47
+ // Precedência do account linking:
48
+ // 1. Identidade de provider já ligada → loga essa conta.
49
+ // 2. Senão, e-mail conhecido → acha por e-mail e LIGA a identidade (linking).
50
+ // 3. Senão → cria conta nova e liga a identidade.
51
+ let user = await store.findByProviderIdentity(provider, profile.id);
52
+ if (!user && email) {
53
+ const byEmail = await store.findByEmail(email);
54
+ if (byEmail) {
55
+ await store.linkProviderIdentity({
56
+ accountId: byEmail.id,
57
+ provider,
58
+ providerUserId: profile.id,
59
+ email,
60
+ });
61
+ user = byEmail;
62
+ }
63
+ }
64
+ if (!user) {
65
+ // Sem e-mail não há como criar/identificar uma conta — volta ao login.
66
+ if (!email) {
67
+ ctx.session.forget(UID_SESSION_KEY);
68
+ return ctx.response.redirect(backToLogin);
69
+ }
70
+ const created = await store.create({
71
+ email,
72
+ password: randomUUID(),
73
+ fullName: profile.name ?? null,
74
+ emailVerified: true,
75
+ });
76
+ await store.linkProviderIdentity({
77
+ accountId: created.id,
78
+ provider,
79
+ providerUserId: profile.id,
80
+ email,
81
+ });
82
+ user = created;
83
+ }
84
+ ctx.session.forget(UID_SESSION_KEY);
85
+ // Conclui a interaction OIDC para este usuário (escreve o 303 de volta ao authorize).
86
+ // O cookie de interaction (path '/') sobrevive ao round-trip do provider OAuth.
87
+ await service.interactions.completeLogin(ctx, user.id);
88
+ }
89
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Helper de exceções de CSRF para as rotas machine-to-machine do AuthKit.
3
+ *
4
+ * Os endpoints do IdP (token/introspection/PAT) e o back-channel logout são
5
+ * server-to-server (sem browser/token XSRF). Em vez de cada app reescrever a
6
+ * checagem de URL no `config/shield.ts`, use este helper:
7
+ *
8
+ * ```ts
9
+ * // config/shield.ts
10
+ * import { authkitCsrfExceptions } from '@adonis-agora/authkit-server'
11
+ * csrf: {
12
+ * enabled: true,
13
+ * exceptRoutes: (ctx) => authkitCsrfExceptions(ctx.request.url(), { mountPath: '/oidc' })
14
+ * || ctx.request.url().includes('/api'),
15
+ * }
16
+ * ```
17
+ */
18
+ export interface AuthkitCsrfOptions {
19
+ /** mountPath do IdP (mesmo de defineConfig/registerAuthHost). Default: `/oidc`. */
20
+ mountPath?: string;
21
+ /** Inclui a rota de back-channel logout do CLIENT (default: `/auth/backchannel-logout`). */
22
+ backchannelLogoutPath?: string | false;
23
+ }
24
+ /**
25
+ * Retorna `true` quando `url` é uma rota AuthKit que deve ser ISENTA de CSRF
26
+ * (machine-to-machine). Cobre o mountPath do IdP, a introspecção de PAT e a
27
+ * rota de back-channel logout do client.
28
+ */
29
+ export declare function authkitCsrfExceptions(url: string, options?: AuthkitCsrfOptions): boolean;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Retorna `true` quando `url` é uma rota AuthKit que deve ser ISENTA de CSRF
3
+ * (machine-to-machine). Cobre o mountPath do IdP, a introspecção de PAT e a
4
+ * rota de back-channel logout do client.
5
+ */
6
+ export function authkitCsrfExceptions(url, options = {}) {
7
+ const mountPath = options.mountPath ?? '/oidc';
8
+ const backchannel = options.backchannelLogoutPath === false
9
+ ? null
10
+ : (options.backchannelLogoutPath ?? '/auth/backchannel-logout');
11
+ return (url.includes(mountPath) ||
12
+ url.includes('/authkit/pat') ||
13
+ (backchannel !== null && url === backchannel));
14
+ }