@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.
- package/LICENSE +21 -0
- package/README.md +158 -0
- package/build/assets/grafana/authkit-dashboard.json +118 -0
- package/build/commands/clients_create.d.ts +27 -0
- package/build/commands/clients_create.js +121 -0
- package/build/commands/commands.json +292 -0
- package/build/commands/configure.d.ts +2 -0
- package/build/commands/configure.js +45 -0
- package/build/commands/doctor.d.ts +10 -0
- package/build/commands/doctor.js +113 -0
- package/build/commands/eject.d.ts +11 -0
- package/build/commands/eject.js +96 -0
- package/build/commands/expire_scan.d.ts +28 -0
- package/build/commands/expire_scan.js +92 -0
- package/build/commands/import_users.d.ts +17 -0
- package/build/commands/import_users.js +80 -0
- package/build/commands/keys_rotate.d.ts +21 -0
- package/build/commands/keys_rotate.js +126 -0
- package/build/commands/main.d.ts +12 -0
- package/build/commands/main.js +38 -0
- package/build/commands/settings_get.d.ts +18 -0
- package/build/commands/settings_get.js +43 -0
- package/build/commands/settings_list.d.ts +17 -0
- package/build/commands/settings_list.js +39 -0
- package/build/commands/settings_set.d.ts +20 -0
- package/build/commands/settings_set.js +55 -0
- package/build/commands/settings_unset.d.ts +18 -0
- package/build/commands/settings_unset.js +46 -0
- package/build/commands/ui_preset.d.ts +4 -0
- package/build/commands/ui_preset.js +32 -0
- package/build/database/migrations/make_authkit_oidc_table.d.ts +6 -0
- package/build/database/migrations/make_authkit_oidc_table.js +19 -0
- package/build/host/ui/admin.html +29 -0
- package/build/host/views/account/apps.edge +59 -0
- package/build/host/views/account/confirm.edge +70 -0
- package/build/host/views/account/email-confirmed.edge +16 -0
- package/build/host/views/account/login.edge +33 -0
- package/build/host/views/account/mfa.edge +152 -0
- package/build/host/views/account/orgs.edge +58 -0
- package/build/host/views/account/security.edge +215 -0
- package/build/host/views/account/tokens.edge +75 -0
- package/build/host/views/consent.edge +20 -0
- package/build/host/views/forgot.edge +43 -0
- package/build/host/views/login.edge +251 -0
- package/build/host/views/maintenance.edge +32 -0
- package/build/host/views/mfa-challenge.edge +107 -0
- package/build/host/views/otp-unlock.edge +40 -0
- package/build/host/views/partials/styles.edge +2 -0
- package/build/host/views/reset.edge +30 -0
- package/build/host/views/signup.edge +62 -0
- package/build/host/views/verify-email.edge +17 -0
- package/build/index.d.ts +115 -0
- package/build/index.js +76 -0
- package/build/password/common_passwords.txt +10000 -0
- package/build/providers/authkit_server_provider.d.ts +27 -0
- package/build/providers/authkit_server_provider.js +242 -0
- package/build/src/accounts/account_store.d.ts +578 -0
- package/build/src/accounts/account_store.js +60 -0
- package/build/src/accounts/lucid_account_store.d.ts +156 -0
- package/build/src/accounts/lucid_account_store.js +294 -0
- package/build/src/accounts/lucid_store/core.d.ts +9 -0
- package/build/src/accounts/lucid_store/core.js +306 -0
- package/build/src/accounts/lucid_store/mfa.d.ts +15 -0
- package/build/src/accounts/lucid_store/mfa.js +108 -0
- package/build/src/accounts/lucid_store/organizations.d.ts +13 -0
- package/build/src/accounts/lucid_store/organizations.js +294 -0
- package/build/src/accounts/lucid_store/password_hygiene.d.ts +20 -0
- package/build/src/accounts/lucid_store/password_hygiene.js +130 -0
- package/build/src/accounts/lucid_store/provider_identity.d.ts +8 -0
- package/build/src/accounts/lucid_store/provider_identity.js +59 -0
- package/build/src/accounts/lucid_store/shared.d.ts +113 -0
- package/build/src/accounts/lucid_store/shared.js +130 -0
- package/build/src/accounts/lucid_store/status_profile.d.ts +34 -0
- package/build/src/accounts/lucid_store/status_profile.js +100 -0
- package/build/src/accounts/lucid_store/webauthn.d.ts +8 -0
- package/build/src/accounts/lucid_store/webauthn.js +140 -0
- package/build/src/accounts/lucid_stores.d.ts +45 -0
- package/build/src/accounts/lucid_stores.js +30 -0
- package/build/src/adapters/adapter_contract.d.ts +37 -0
- package/build/src/adapters/adapter_contract.js +1 -0
- package/build/src/adapters/database_adapter.d.ts +21 -0
- package/build/src/adapters/database_adapter.js +79 -0
- package/build/src/adapters/factory.d.ts +30 -0
- package/build/src/adapters/factory.js +43 -0
- package/build/src/adapters/redis_adapter.d.ts +24 -0
- package/build/src/adapters/redis_adapter.js +122 -0
- package/build/src/audit/audit_sink.d.ts +63 -0
- package/build/src/audit/audit_sink.js +1 -0
- package/build/src/audit/lucid_audit_sink.d.ts +10 -0
- package/build/src/audit/lucid_audit_sink.js +99 -0
- package/build/src/commands/expire_scan_command.d.ts +60 -0
- package/build/src/commands/expire_scan_command.js +229 -0
- package/build/src/commands/import_clients.d.ts +40 -0
- package/build/src/commands/import_clients.js +79 -0
- package/build/src/commands/import_users.d.ts +51 -0
- package/build/src/commands/import_users.js +94 -0
- package/build/src/commands/resolve_config.d.ts +13 -0
- package/build/src/commands/resolve_config.js +18 -0
- package/build/src/commands/settings_commands.d.ts +47 -0
- package/build/src/commands/settings_commands.js +270 -0
- package/build/src/controllers/oidc_callback_controller.d.ts +22 -0
- package/build/src/controllers/oidc_callback_controller.js +33 -0
- package/build/src/define_config.d.ts +772 -0
- package/build/src/define_config.js +351 -0
- package/build/src/doctor/checks.d.ts +197 -0
- package/build/src/doctor/checks.js +858 -0
- package/build/src/events/dispatcher.d.ts +45 -0
- package/build/src/events/dispatcher.js +117 -0
- package/build/src/host/account_api/account_api_controller.d.ts +245 -0
- package/build/src/host/account_api/account_api_controller.js +827 -0
- package/build/src/host/account_deletion_ops.d.ts +80 -0
- package/build/src/host/account_deletion_ops.js +118 -0
- package/build/src/host/account_deletion_service.d.ts +63 -0
- package/build/src/host/account_deletion_service.js +133 -0
- package/build/src/host/account_export_service.d.ts +76 -0
- package/build/src/host/account_export_service.js +140 -0
- package/build/src/host/account_home.d.ts +11 -0
- package/build/src/host/account_home.js +11 -0
- package/build/src/host/account_lockout.d.ts +86 -0
- package/build/src/host/account_lockout.js +185 -0
- package/build/src/host/active_org_cookie.d.ts +28 -0
- package/build/src/host/active_org_cookie.js +47 -0
- package/build/src/host/admin_api/admin_api_guard.d.ts +16 -0
- package/build/src/host/admin_api/admin_api_guard.js +59 -0
- package/build/src/host/admin_api/admin_orgs_service.d.ts +125 -0
- package/build/src/host/admin_api/admin_orgs_service.js +324 -0
- package/build/src/host/admin_api/admin_users_service.d.ts +163 -0
- package/build/src/host/admin_api/admin_users_service.js +308 -0
- package/build/src/host/admin_api/api_clients_controller.d.ts +54 -0
- package/build/src/host/admin_api/api_clients_controller.js +89 -0
- package/build/src/host/admin_api/api_keys_controller.d.ts +19 -0
- package/build/src/host/admin_api/api_keys_controller.js +36 -0
- package/build/src/host/admin_api/api_misc_controller.d.ts +19 -0
- package/build/src/host/admin_api/api_misc_controller.js +44 -0
- package/build/src/host/admin_api/api_orgs_controller.d.ts +108 -0
- package/build/src/host/admin_api/api_orgs_controller.js +189 -0
- package/build/src/host/admin_api/api_settings_controller.d.ts +55 -0
- package/build/src/host/admin_api/api_settings_controller.js +134 -0
- package/build/src/host/admin_api/api_users_controller.d.ts +108 -0
- package/build/src/host/admin_api/api_users_controller.js +187 -0
- package/build/src/host/admin_api/dto.d.ts +131 -0
- package/build/src/host/admin_api/dto.js +122 -0
- package/build/src/host/admin_api/token_verify_service.d.ts +34 -0
- package/build/src/host/admin_api/token_verify_service.js +74 -0
- package/build/src/host/admin_clients_service.d.ts +88 -0
- package/build/src/host/admin_clients_service.js +181 -0
- package/build/src/host/admin_console/admin_shell_controller.d.ts +27 -0
- package/build/src/host/admin_console/admin_shell_controller.js +167 -0
- package/build/src/host/admin_console/console_audit_controller.d.ts +17 -0
- package/build/src/host/admin_console/console_audit_controller.js +25 -0
- package/build/src/host/admin_console/console_clients_controller.d.ts +53 -0
- package/build/src/host/admin_console/console_clients_controller.js +102 -0
- package/build/src/host/admin_console/console_impersonation_controller.d.ts +23 -0
- package/build/src/host/admin_console/console_impersonation_controller.js +45 -0
- package/build/src/host/admin_console/console_keys_controller.d.ts +24 -0
- package/build/src/host/admin_console/console_keys_controller.js +41 -0
- package/build/src/host/admin_console/console_orgs_controller.d.ts +96 -0
- package/build/src/host/admin_console/console_orgs_controller.js +238 -0
- package/build/src/host/admin_console/console_overview_controller.d.ts +27 -0
- package/build/src/host/admin_console/console_overview_controller.js +44 -0
- package/build/src/host/admin_console/console_roles_controller.d.ts +31 -0
- package/build/src/host/admin_console/console_roles_controller.js +108 -0
- package/build/src/host/admin_console/console_sessions_controller.d.ts +91 -0
- package/build/src/host/admin_console/console_sessions_controller.js +125 -0
- package/build/src/host/admin_console/console_settings_controller.d.ts +47 -0
- package/build/src/host/admin_console/console_settings_controller.js +115 -0
- package/build/src/host/admin_console/console_users_controller.d.ts +110 -0
- package/build/src/host/admin_console/console_users_controller.js +212 -0
- package/build/src/host/admin_prefix.d.ts +50 -0
- package/build/src/host/admin_prefix.js +77 -0
- package/build/src/host/admin_sessions_service.d.ts +119 -0
- package/build/src/host/admin_sessions_service.js +284 -0
- package/build/src/host/admin_stats_service.d.ts +44 -0
- package/build/src/host/admin_stats_service.js +130 -0
- package/build/src/host/admin_validators.d.ts +247 -0
- package/build/src/host/admin_validators.js +197 -0
- package/build/src/host/augmentations.d.ts +12 -0
- package/build/src/host/augmentations.js +1 -0
- package/build/src/host/auth_host_config.d.ts +22 -0
- package/build/src/host/auth_host_config.js +13 -0
- package/build/src/host/avatar_storage.d.ts +68 -0
- package/build/src/host/avatar_storage.js +166 -0
- package/build/src/host/bot_protection.d.ts +187 -0
- package/build/src/host/bot_protection.js +132 -0
- package/build/src/host/branding.d.ts +19 -0
- package/build/src/host/branding.js +8 -0
- package/build/src/host/config_locks.d.ts +38 -0
- package/build/src/host/config_locks.js +70 -0
- package/build/src/host/console_session.d.ts +27 -0
- package/build/src/host/console_session.js +36 -0
- package/build/src/host/controllers/account_apps_controller.d.ts +15 -0
- package/build/src/host/controllers/account_apps_controller.js +61 -0
- package/build/src/host/controllers/account_confirm_controller.d.ts +24 -0
- package/build/src/host/controllers/account_confirm_controller.js +144 -0
- package/build/src/host/controllers/account_mfa_controller.d.ts +28 -0
- package/build/src/host/controllers/account_mfa_controller.js +208 -0
- package/build/src/host/controllers/account_orgs_controller.d.ts +80 -0
- package/build/src/host/controllers/account_orgs_controller.js +401 -0
- package/build/src/host/controllers/account_security_controller.d.ts +43 -0
- package/build/src/host/controllers/account_security_controller.js +546 -0
- package/build/src/host/controllers/account_session_controller.d.ts +21 -0
- package/build/src/host/controllers/account_session_controller.js +113 -0
- package/build/src/host/controllers/account_tokens_controller.d.ts +7 -0
- package/build/src/host/controllers/account_tokens_controller.js +67 -0
- package/build/src/host/controllers/interaction_controller.d.ts +125 -0
- package/build/src/host/controllers/interaction_controller.js +981 -0
- package/build/src/host/controllers/pat_introspection_controller.d.ts +22 -0
- package/build/src/host/controllers/pat_introspection_controller.js +46 -0
- package/build/src/host/controllers/registration_controller.d.ts +18 -0
- package/build/src/host/controllers/registration_controller.js +382 -0
- package/build/src/host/controllers/social_controller.d.ts +8 -0
- package/build/src/host/controllers/social_controller.js +89 -0
- package/build/src/host/csrf.d.ts +29 -0
- package/build/src/host/csrf.js +14 -0
- package/build/src/host/default_mailer.d.ts +112 -0
- package/build/src/host/default_mailer.js +417 -0
- package/build/src/host/durable/account_deletion_workflow.d.ts +48 -0
- package/build/src/host/durable/account_deletion_workflow.js +86 -0
- package/build/src/host/durable/account_export_workflow.d.ts +68 -0
- package/build/src/host/durable/account_export_workflow.js +93 -0
- package/build/src/host/durable/index.d.ts +68 -0
- package/build/src/host/durable/index.js +77 -0
- package/build/src/host/email_templates.d.ts +39 -0
- package/build/src/host/email_templates.js +69 -0
- package/build/src/host/geo.d.ts +22 -0
- package/build/src/host/geo.js +39 -0
- package/build/src/host/i18n.d.ts +1416 -0
- package/build/src/host/i18n.js +1583 -0
- package/build/src/host/impersonation.d.ts +25 -0
- package/build/src/host/impersonation.js +31 -0
- package/build/src/host/key_rotation.d.ts +14 -0
- package/build/src/host/key_rotation.js +27 -0
- package/build/src/host/key_rotation_actions.d.ts +42 -0
- package/build/src/host/key_rotation_actions.js +27 -0
- package/build/src/host/login_attempt.d.ts +98 -0
- package/build/src/host/login_attempt.js +211 -0
- package/build/src/host/login_notify.d.ts +27 -0
- package/build/src/host/login_notify.js +142 -0
- package/build/src/host/middleware/account_auth.d.ts +7 -0
- package/build/src/host/middleware/account_auth.js +11 -0
- package/build/src/host/otp_lockout.d.ts +103 -0
- package/build/src/host/otp_lockout.js +221 -0
- package/build/src/host/rate_limit.d.ts +39 -0
- package/build/src/host/rate_limit.js +94 -0
- package/build/src/host/register_auth_host.d.ts +97 -0
- package/build/src/host/register_auth_host.js +466 -0
- package/build/src/host/renderers/edge_renderer.d.ts +12 -0
- package/build/src/host/renderers/edge_renderer.js +38 -0
- package/build/src/host/renderers/inertia_renderer.d.ts +70 -0
- package/build/src/host/renderers/inertia_renderer.js +54 -0
- package/build/src/host/runtime_settings.d.ts +181 -0
- package/build/src/host/runtime_settings.js +307 -0
- package/build/src/host/runtime_toggles.d.ts +807 -0
- package/build/src/host/runtime_toggles.js +784 -0
- package/build/src/host/security_notice_service.d.ts +36 -0
- package/build/src/host/security_notice_service.js +87 -0
- package/build/src/host/session_context.d.ts +23 -0
- package/build/src/host/session_context.js +89 -0
- package/build/src/host/sudo_mode.d.ts +56 -0
- package/build/src/host/sudo_mode.js +99 -0
- package/build/src/host/svg_chart.d.ts +15 -0
- package/build/src/host/svg_chart.js +45 -0
- package/build/src/host/trusted_device.d.ts +61 -0
- package/build/src/host/trusted_device.js +65 -0
- package/build/src/host/ui-dist/assets/index-CRWcmsex.js +137 -0
- package/build/src/host/ui-dist/assets/index-DTSmD4RU.css +1 -0
- package/build/src/host/ui-dist/index.html +17 -0
- package/build/src/host/user_agent.d.ts +18 -0
- package/build/src/host/user_agent.js +50 -0
- package/build/src/host/validators.d.ts +127 -0
- package/build/src/host/validators.js +53 -0
- package/build/src/keys/jwks_manager.d.ts +6 -0
- package/build/src/keys/jwks_manager.js +11 -0
- package/build/src/keys/keystore.d.ts +52 -0
- package/build/src/keys/keystore.js +68 -0
- package/build/src/keys/keystore_codec.d.ts +20 -0
- package/build/src/keys/keystore_codec.js +42 -0
- package/build/src/keys/keystore_crypto.d.ts +9 -0
- package/build/src/keys/keystore_crypto.js +27 -0
- package/build/src/keys/keystore_manager.d.ts +43 -0
- package/build/src/keys/keystore_manager.js +104 -0
- package/build/src/keys/keystore_vault.d.ts +113 -0
- package/build/src/keys/keystore_vault.js +265 -0
- package/build/src/mixins/json_column.d.ts +33 -0
- package/build/src/mixins/json_column.js +38 -0
- package/build/src/mixins/with_audit_log.d.ts +19 -0
- package/build/src/mixins/with_audit_log.js +39 -0
- package/build/src/mixins/with_auth_user.d.ts +24 -0
- package/build/src/mixins/with_auth_user.js +46 -0
- package/build/src/mixins/with_credentials.d.ts +20 -0
- package/build/src/mixins/with_credentials.js +29 -0
- package/build/src/mixins/with_mfa.d.ts +35 -0
- package/build/src/mixins/with_mfa.js +21 -0
- package/build/src/mixins/with_personal_access_token.d.ts +19 -0
- package/build/src/mixins/with_personal_access_token.js +42 -0
- package/build/src/mixins/with_provider_identity.d.ts +20 -0
- package/build/src/mixins/with_provider_identity.js +32 -0
- package/build/src/mixins/with_webauthn_credential.d.ts +37 -0
- package/build/src/mixins/with_webauthn_credential.js +46 -0
- package/build/src/observability/diagnostics_bridge.d.ts +6 -0
- package/build/src/observability/diagnostics_bridge.js +27 -0
- package/build/src/observability/metrics_controller.d.ts +5 -0
- package/build/src/observability/metrics_controller.js +24 -0
- package/build/src/observability/metrics_service.d.ts +2 -0
- package/build/src/observability/metrics_service.js +7 -0
- package/build/src/observability/otel_recorder.d.ts +10 -0
- package/build/src/observability/otel_recorder.js +59 -0
- package/build/src/observability/telescope/data_providers.d.ts +24 -0
- package/build/src/observability/telescope/data_providers.js +235 -0
- package/build/src/observability/telescope/extension.d.ts +29 -0
- package/build/src/observability/telescope/extension.js +167 -0
- package/build/src/observability/telescope/index.d.ts +8 -0
- package/build/src/observability/telescope/index.js +8 -0
- package/build/src/observability/wire_provider_events.d.ts +12 -0
- package/build/src/observability/wire_provider_events.js +30 -0
- package/build/src/password/common_passwords.d.ts +31 -0
- package/build/src/password/common_passwords.js +73 -0
- package/build/src/password/password_manager.d.ts +163 -0
- package/build/src/password/password_manager.js +191 -0
- package/build/src/password/policy.d.ts +71 -0
- package/build/src/password/policy.js +55 -0
- package/build/src/password/pwned.d.ts +36 -0
- package/build/src/password/pwned.js +52 -0
- package/build/src/pat/lucid_pat_store.d.ts +6 -0
- package/build/src/pat/lucid_pat_store.js +62 -0
- package/build/src/pat/pat_store.d.ts +31 -0
- package/build/src/pat/pat_store.js +1 -0
- package/build/src/pat/pat_tokens.d.ts +4 -0
- package/build/src/pat/pat_tokens.js +9 -0
- package/build/src/provider/build_provider.d.ts +45 -0
- package/build/src/provider/build_provider.js +219 -0
- package/build/src/provider/device_sources.d.ts +6 -0
- package/build/src/provider/device_sources.js +65 -0
- package/build/src/provider/interaction_actions.d.ts +36 -0
- package/build/src/provider/interaction_actions.js +55 -0
- package/build/src/provider/key_rotation_scheduler.d.ts +28 -0
- package/build/src/provider/key_rotation_scheduler.js +40 -0
- package/build/src/provider/keystore_reload.d.ts +21 -0
- package/build/src/provider/keystore_reload.js +39 -0
- package/build/src/provider/logout_sources.d.ts +13 -0
- package/build/src/provider/logout_sources.js +64 -0
- package/build/src/provider/oidc_service.d.ts +81 -0
- package/build/src/provider/oidc_service.js +254 -0
- package/build/src/provider/single_flight_lock.d.ts +18 -0
- package/build/src/provider/single_flight_lock.js +31 -0
- package/build/src/provider/token_exchange.d.ts +21 -0
- package/build/src/provider/token_exchange.js +124 -0
- package/build/src/register_routes.d.ts +16 -0
- package/build/src/register_routes.js +21 -0
- package/build/src/schema/ensure.d.ts +41 -0
- package/build/src/schema/ensure.js +262 -0
- package/build/stubs/config/authkit.stub +20 -0
- package/build/stubs/config/authkit_react.stub +52 -0
- package/build/stubs/main.d.ts +1 -0
- package/build/stubs/main.js +2 -0
- package/build/stubs/models/auth_user.stub +22 -0
- package/build/stubs/ui/edge/views/consent.edge +13 -0
- package/build/stubs/ui/edge/views/login.edge +19 -0
- package/build/stubs/ui/react/components/auth_shell.tsx +67 -0
- package/build/stubs/ui/react/pages/account/login.tsx +56 -0
- package/build/stubs/ui/react/pages/account/mfa.tsx +132 -0
- package/build/stubs/ui/react/pages/account/tokens.tsx +88 -0
- package/build/stubs/ui/react/pages/consent.tsx +39 -0
- package/build/stubs/ui/react/pages/forgot.tsx +44 -0
- package/build/stubs/ui/react/pages/login.tsx +171 -0
- package/build/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
- package/build/stubs/ui/react/pages/reset.tsx +58 -0
- package/build/stubs/ui/react/pages/signup.tsx +78 -0
- package/build/stubs/ui/react/pages/verify-email.tsx +24 -0
- package/build/types.d.ts +7 -0
- package/build/types.js +1 -0
- package/package.json +147 -0
- package/stubs/config/authkit.stub +20 -0
- package/stubs/config/authkit_react.stub +52 -0
- package/stubs/main.ts +2 -0
- package/stubs/models/auth_user.stub +22 -0
- package/stubs/ui/edge/views/consent.edge +13 -0
- package/stubs/ui/edge/views/login.edge +19 -0
- package/stubs/ui/react/components/auth_shell.tsx +67 -0
- package/stubs/ui/react/pages/account/login.tsx +56 -0
- package/stubs/ui/react/pages/account/mfa.tsx +132 -0
- package/stubs/ui/react/pages/account/tokens.tsx +88 -0
- package/stubs/ui/react/pages/consent.tsx +39 -0
- package/stubs/ui/react/pages/forgot.tsx +44 -0
- package/stubs/ui/react/pages/login.tsx +171 -0
- package/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
- package/stubs/ui/react/pages/reset.tsx +58 -0
- package/stubs/ui/react/pages/signup.tsx +78 -0
- package/stubs/ui/react/pages/verify-email.tsx +24 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import '../augmentations.js';
|
|
2
|
+
export const ACCOUNT_SESSION_KEY = 'account_user_id';
|
|
3
|
+
export default class AccountAuthMiddleware {
|
|
4
|
+
async handle(ctx, next) {
|
|
5
|
+
const userId = ctx.session.get(ACCOUNT_SESSION_KEY);
|
|
6
|
+
if (!userId) {
|
|
7
|
+
return ctx.response.redirect('/account/login');
|
|
8
|
+
}
|
|
9
|
+
return next();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTP Lockout — trava o fator TOTP/recovery após N falhas consecutivas.
|
|
3
|
+
*
|
|
4
|
+
* Implementação paralela ao account_lockout.ts, mas keyed por accountId (não por
|
|
5
|
+
* e-mail) e limitando o FATOR (não a conta inteira). Usa a mesma infraestrutura do
|
|
6
|
+
* `@adonisjs/limiter` (peer/opt-in, fail-safe).
|
|
7
|
+
*
|
|
8
|
+
* Esquema de chaves (namespaced por accountId):
|
|
9
|
+
* `authkit_otp_fail:<accountId>` — contador de falhas TOTP/recovery.
|
|
10
|
+
* `authkit_otp_lock:<accountId>` — flag de travamento do fator OTP.
|
|
11
|
+
*
|
|
12
|
+
* Storage do token de desbloqueio: prefixo `ou:` no campo `passwordResetToken`
|
|
13
|
+
* do model do usuário (mesma abordagem de magic link `ml:` e email change `ec:`).
|
|
14
|
+
* Sem migração necessária — reutiliza coluna existente.
|
|
15
|
+
*
|
|
16
|
+
* No-op total quando o `@adonisjs/limiter` não está instalado.
|
|
17
|
+
*/
|
|
18
|
+
import type { AuditSink } from '../audit/audit_sink.js';
|
|
19
|
+
import type { SettingsCapability } from './runtime_settings.js';
|
|
20
|
+
export interface OtpLockoutSetting {
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
maxAttempts?: number;
|
|
23
|
+
unlockTtlHours?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface ResolvedOtpLockoutSetting {
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
maxAttempts: number;
|
|
28
|
+
unlockTtlHours: number;
|
|
29
|
+
}
|
|
30
|
+
export declare const OTP_LOCKOUT_DEFAULTS: ResolvedOtpLockoutSetting;
|
|
31
|
+
/**
|
|
32
|
+
* Resolve a setting `otp_lockout` em runtime (fail-safe).
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveEffectiveOtpLockout(settings: SettingsCapability): Promise<ResolvedOtpLockoutSetting>;
|
|
35
|
+
/** Prefixo do token de desbloqueio OTP no campo passwordResetToken. */
|
|
36
|
+
export declare const OTP_UNLOCK_TOKEN_PREFIX = "ou:";
|
|
37
|
+
/**
|
|
38
|
+
* Gera um token de desbloqueio OTP para armazenar no model do usuário.
|
|
39
|
+
* O token bruto vai no e-mail; o hash SHA-256 fica no DB (mesmo padrão
|
|
40
|
+
* de email_change e reset de senha).
|
|
41
|
+
*
|
|
42
|
+
* @returns `{ raw, prefix }` — `raw` vai na URL; `prefix + sha256(raw)` no DB.
|
|
43
|
+
*/
|
|
44
|
+
export declare function generateOtpUnlockToken(): {
|
|
45
|
+
raw: string;
|
|
46
|
+
dbValue: string;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Converte um token bruto recebido na URL no valor de DB correspondente.
|
|
50
|
+
*/
|
|
51
|
+
export declare function rawToDbOtpUnlockToken(raw: string): string;
|
|
52
|
+
type LimiterService = any;
|
|
53
|
+
/** Reaponta o loader (usado em testes). @internal */
|
|
54
|
+
export declare function __setOtpLockoutLimiterLoaderForTests(fn: (() => Promise<LimiterService | null>) | undefined): void;
|
|
55
|
+
export interface OtpLockoutAuditContext {
|
|
56
|
+
sink?: AuditSink;
|
|
57
|
+
ip?: string | null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Logger mínimo (subconjunto do logger do AdonisJS) para observar as degradações
|
|
61
|
+
* fail-safe. Sem ele, os caminhos de erro continuam silenciosos (backward-compat).
|
|
62
|
+
*/
|
|
63
|
+
export interface OtpLockoutLogger {
|
|
64
|
+
warn(obj: unknown, msg?: string): void;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Gerencia o lockout do fator OTP (TOTP + recovery) por accountId.
|
|
68
|
+
* No-op quando o limiter não está disponível.
|
|
69
|
+
*/
|
|
70
|
+
export declare class OtpLockout {
|
|
71
|
+
private cfg;
|
|
72
|
+
private logger?;
|
|
73
|
+
constructor(cfg: ResolvedOtpLockoutSetting, logger?: OtpLockoutLogger | undefined);
|
|
74
|
+
private failKey;
|
|
75
|
+
private lockKey;
|
|
76
|
+
private limiter;
|
|
77
|
+
/** Store de contagem de falhas (janela = unlockTtlHours * 2 s). */
|
|
78
|
+
private failStore;
|
|
79
|
+
/** Store da flag de lock (requests=1, duration=unlockTtlHours). */
|
|
80
|
+
private lockStore;
|
|
81
|
+
/**
|
|
82
|
+
* Verifica se o fator OTP está travado para a conta.
|
|
83
|
+
* FAIL-SAFE: erro → `false` (nunca bloqueia por falha de infra).
|
|
84
|
+
*/
|
|
85
|
+
isLocked(accountId: string): Promise<boolean>;
|
|
86
|
+
/**
|
|
87
|
+
* Registra uma falha de TOTP/recovery. Ao atingir maxAttempts, trava o fator.
|
|
88
|
+
* Emite `otp.locked` no audit (uma vez, na transição).
|
|
89
|
+
* FAIL-SAFE: erros do limiter nunca propagam.
|
|
90
|
+
*/
|
|
91
|
+
recordFailure(accountId: string, audit?: OtpLockoutAuditContext): Promise<boolean>;
|
|
92
|
+
/**
|
|
93
|
+
* Limpa o estado de falhas OTP após um código correto.
|
|
94
|
+
* FAIL-SAFE: erros do limiter nunca propagam.
|
|
95
|
+
*/
|
|
96
|
+
clearFailures(accountId: string): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Zera o estado completo (falhas + lock) — chamado pelo `GET /auth/otp-unlock/:token`.
|
|
99
|
+
*/
|
|
100
|
+
unlock(accountId: string): Promise<void>;
|
|
101
|
+
}
|
|
102
|
+
export declare function createOtpLockout(cfg: ResolvedOtpLockoutSetting, logger?: OtpLockoutLogger): OtpLockout;
|
|
103
|
+
export {};
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTP Lockout — trava o fator TOTP/recovery após N falhas consecutivas.
|
|
3
|
+
*
|
|
4
|
+
* Implementação paralela ao account_lockout.ts, mas keyed por accountId (não por
|
|
5
|
+
* e-mail) e limitando o FATOR (não a conta inteira). Usa a mesma infraestrutura do
|
|
6
|
+
* `@adonisjs/limiter` (peer/opt-in, fail-safe).
|
|
7
|
+
*
|
|
8
|
+
* Esquema de chaves (namespaced por accountId):
|
|
9
|
+
* `authkit_otp_fail:<accountId>` — contador de falhas TOTP/recovery.
|
|
10
|
+
* `authkit_otp_lock:<accountId>` — flag de travamento do fator OTP.
|
|
11
|
+
*
|
|
12
|
+
* Storage do token de desbloqueio: prefixo `ou:` no campo `passwordResetToken`
|
|
13
|
+
* do model do usuário (mesma abordagem de magic link `ml:` e email change `ec:`).
|
|
14
|
+
* Sem migração necessária — reutiliza coluna existente.
|
|
15
|
+
*
|
|
16
|
+
* No-op total quando o `@adonisjs/limiter` não está instalado.
|
|
17
|
+
*/
|
|
18
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
19
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
20
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
21
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return path;
|
|
25
|
+
};
|
|
26
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
27
|
+
import { SETTING_KEYS } from './runtime_toggles.js';
|
|
28
|
+
export const OTP_LOCKOUT_DEFAULTS = {
|
|
29
|
+
enabled: true,
|
|
30
|
+
maxAttempts: 5,
|
|
31
|
+
unlockTtlHours: 24,
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Resolve a setting `otp_lockout` em runtime (fail-safe).
|
|
35
|
+
*/
|
|
36
|
+
export async function resolveEffectiveOtpLockout(settings) {
|
|
37
|
+
try {
|
|
38
|
+
const raw = await settings.getSetting(SETTING_KEYS.OTP_LOCKOUT);
|
|
39
|
+
if (raw === null || raw === undefined)
|
|
40
|
+
return OTP_LOCKOUT_DEFAULTS;
|
|
41
|
+
if (typeof raw !== 'object' || Array.isArray(raw))
|
|
42
|
+
return OTP_LOCKOUT_DEFAULTS;
|
|
43
|
+
const s = raw;
|
|
44
|
+
return {
|
|
45
|
+
enabled: typeof s.enabled === 'boolean' ? s.enabled : OTP_LOCKOUT_DEFAULTS.enabled,
|
|
46
|
+
maxAttempts: typeof s.maxAttempts === 'number' && s.maxAttempts >= 1
|
|
47
|
+
? Math.floor(s.maxAttempts)
|
|
48
|
+
: OTP_LOCKOUT_DEFAULTS.maxAttempts,
|
|
49
|
+
unlockTtlHours: typeof s.unlockTtlHours === 'number' && s.unlockTtlHours >= 1
|
|
50
|
+
? Math.floor(s.unlockTtlHours)
|
|
51
|
+
: OTP_LOCKOUT_DEFAULTS.unlockTtlHours,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return OTP_LOCKOUT_DEFAULTS;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Token de desbloqueio (OTP unlock)
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/** Prefixo do token de desbloqueio OTP no campo passwordResetToken. */
|
|
62
|
+
export const OTP_UNLOCK_TOKEN_PREFIX = 'ou:';
|
|
63
|
+
/**
|
|
64
|
+
* Gera um token de desbloqueio OTP para armazenar no model do usuário.
|
|
65
|
+
* O token bruto vai no e-mail; o hash SHA-256 fica no DB (mesmo padrão
|
|
66
|
+
* de email_change e reset de senha).
|
|
67
|
+
*
|
|
68
|
+
* @returns `{ raw, prefix }` — `raw` vai na URL; `prefix + sha256(raw)` no DB.
|
|
69
|
+
*/
|
|
70
|
+
export function generateOtpUnlockToken() {
|
|
71
|
+
const raw = randomBytes(32).toString('hex');
|
|
72
|
+
const hash = createHash('sha256').update(raw).digest('hex');
|
|
73
|
+
return { raw, dbValue: `${OTP_UNLOCK_TOKEN_PREFIX}${hash}` };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Converte um token bruto recebido na URL no valor de DB correspondente.
|
|
77
|
+
*/
|
|
78
|
+
export function rawToDbOtpUnlockToken(raw) {
|
|
79
|
+
const hash = createHash('sha256').update(raw).digest('hex');
|
|
80
|
+
return `${OTP_UNLOCK_TOKEN_PREFIX}${hash}`;
|
|
81
|
+
}
|
|
82
|
+
let limiterPromise;
|
|
83
|
+
async function loadLimiter() {
|
|
84
|
+
if (!limiterPromise) {
|
|
85
|
+
const spec = '@adonisjs/limiter/services/main';
|
|
86
|
+
limiterPromise = import(__rewriteRelativeImportExtension(spec))
|
|
87
|
+
.then((m) => m.default ?? null)
|
|
88
|
+
.catch(() => null);
|
|
89
|
+
}
|
|
90
|
+
return limiterPromise;
|
|
91
|
+
}
|
|
92
|
+
/** Reaponta o loader (usado em testes). @internal */
|
|
93
|
+
export function __setOtpLockoutLimiterLoaderForTests(fn) {
|
|
94
|
+
if (fn) {
|
|
95
|
+
limiterPromise = fn();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
limiterPromise = undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Gerencia o lockout do fator OTP (TOTP + recovery) por accountId.
|
|
103
|
+
* No-op quando o limiter não está disponível.
|
|
104
|
+
*/
|
|
105
|
+
export class OtpLockout {
|
|
106
|
+
cfg;
|
|
107
|
+
logger;
|
|
108
|
+
constructor(cfg, logger) {
|
|
109
|
+
this.cfg = cfg;
|
|
110
|
+
this.logger = logger;
|
|
111
|
+
}
|
|
112
|
+
failKey(accountId) {
|
|
113
|
+
return `authkit_otp_fail:${accountId}`;
|
|
114
|
+
}
|
|
115
|
+
lockKey(accountId) {
|
|
116
|
+
return `authkit_otp_lock:${accountId}`;
|
|
117
|
+
}
|
|
118
|
+
async limiter() {
|
|
119
|
+
if (!this.cfg.enabled)
|
|
120
|
+
return null;
|
|
121
|
+
return loadLimiter();
|
|
122
|
+
}
|
|
123
|
+
/** Store de contagem de falhas (janela = unlockTtlHours * 2 s). */
|
|
124
|
+
failStore(l) {
|
|
125
|
+
const opts = { requests: this.cfg.maxAttempts, duration: this.cfg.unlockTtlHours * 3600 * 2 };
|
|
126
|
+
return l.use(opts);
|
|
127
|
+
}
|
|
128
|
+
/** Store da flag de lock (requests=1, duration=unlockTtlHours). */
|
|
129
|
+
lockStore(l) {
|
|
130
|
+
const opts = { requests: 1, duration: this.cfg.unlockTtlHours * 3600 };
|
|
131
|
+
return l.use(opts);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Verifica se o fator OTP está travado para a conta.
|
|
135
|
+
* FAIL-SAFE: erro → `false` (nunca bloqueia por falha de infra).
|
|
136
|
+
*/
|
|
137
|
+
async isLocked(accountId) {
|
|
138
|
+
const l = await this.limiter();
|
|
139
|
+
if (!l || !accountId)
|
|
140
|
+
return false;
|
|
141
|
+
try {
|
|
142
|
+
return await this.lockStore(l).isBlocked(this.lockKey(accountId));
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
// Falha do limiter NUNCA derruba o login — degrada para "não travado". Mas
|
|
146
|
+
// loga: enquanto o limiter estiver quebrado, o lockout de OTP fica desligado.
|
|
147
|
+
this.logger?.warn({ err, accountId }, 'authkit: OTP lockout isLocked check failed (limiter error) — degrading to unlocked (fail-safe); OTP lockout is effectively disabled until the limiter recovers.');
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Registra uma falha de TOTP/recovery. Ao atingir maxAttempts, trava o fator.
|
|
153
|
+
* Emite `otp.locked` no audit (uma vez, na transição).
|
|
154
|
+
* FAIL-SAFE: erros do limiter nunca propagam.
|
|
155
|
+
*/
|
|
156
|
+
async recordFailure(accountId, audit) {
|
|
157
|
+
const l = await this.limiter();
|
|
158
|
+
if (!l || !accountId)
|
|
159
|
+
return false;
|
|
160
|
+
try {
|
|
161
|
+
// Se já está travado, não conta de novo.
|
|
162
|
+
if (await this.lockStore(l).isBlocked(this.lockKey(accountId)))
|
|
163
|
+
return true;
|
|
164
|
+
const failStore = this.failStore(l);
|
|
165
|
+
const res = await failStore.increment(this.failKey(accountId));
|
|
166
|
+
const consumed = res?.consumed ?? 0;
|
|
167
|
+
if (consumed < this.cfg.maxAttempts)
|
|
168
|
+
return false;
|
|
169
|
+
// Transição para travado.
|
|
170
|
+
await this.lockStore(l).block(this.lockKey(accountId), this.cfg.unlockTtlHours * 3600);
|
|
171
|
+
await failStore.delete(this.failKey(accountId));
|
|
172
|
+
await audit?.sink?.record({
|
|
173
|
+
type: 'otp.locked',
|
|
174
|
+
accountId,
|
|
175
|
+
ip: audit?.ip ?? null,
|
|
176
|
+
metadata: { maxAttempts: this.cfg.maxAttempts },
|
|
177
|
+
});
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
// Falha do limiter ao registrar a tentativa: a falha NÃO é contabilizada, o
|
|
182
|
+
// que enfraquece a proteção anti-brute-force do fator OTP. Nunca propaga (o
|
|
183
|
+
// login não pode quebrar por infra), mas loga para não ficar invisível.
|
|
184
|
+
this.logger?.warn({ err, accountId }, 'authkit: OTP lockout recordFailure failed (limiter error) — failure NOT counted; brute-force protection on the OTP factor is degraded until the limiter recovers.');
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Limpa o estado de falhas OTP após um código correto.
|
|
190
|
+
* FAIL-SAFE: erros do limiter nunca propagam.
|
|
191
|
+
*/
|
|
192
|
+
async clearFailures(accountId) {
|
|
193
|
+
const l = await this.limiter();
|
|
194
|
+
if (!l || !accountId)
|
|
195
|
+
return;
|
|
196
|
+
try {
|
|
197
|
+
await this.failStore(l).delete(this.failKey(accountId));
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// no-op
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Zera o estado completo (falhas + lock) — chamado pelo `GET /auth/otp-unlock/:token`.
|
|
205
|
+
*/
|
|
206
|
+
async unlock(accountId) {
|
|
207
|
+
const l = await this.limiter();
|
|
208
|
+
if (!l || !accountId)
|
|
209
|
+
return;
|
|
210
|
+
try {
|
|
211
|
+
await this.failStore(l).delete(this.failKey(accountId));
|
|
212
|
+
await this.lockStore(l).delete(this.lockKey(accountId));
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// no-op
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function createOtpLockout(cfg, logger) {
|
|
220
|
+
return new OtpLockout(cfg, logger);
|
|
221
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
import type { ResolvedRateLimitConfig } from '../define_config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Assinatura mínima de um middleware do AdonisJS. Evita acoplar o tipo concreto
|
|
5
|
+
* do `@adonisjs/limiter` (que pode não estar instalado no host).
|
|
6
|
+
*/
|
|
7
|
+
export type ThrottleMiddleware = (ctx: HttpContext, next: () => Promise<void>) => Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Os throttles construídos para as rotas sensíveis do host-kit.
|
|
10
|
+
* - `login`: compartilhado por login/signup/forgot/reset (keyed por IP).
|
|
11
|
+
* - `introspection`: introspecção de PAT (keyed por IP ou pelo bearer secret).
|
|
12
|
+
*/
|
|
13
|
+
export interface AuthThrottles {
|
|
14
|
+
login: ThrottleMiddleware;
|
|
15
|
+
introspection: ThrottleMiddleware;
|
|
16
|
+
/**
|
|
17
|
+
* Throttle por IP do grupo admin-api (R6). Anti-brute-force REAL da Bearer key:
|
|
18
|
+
* diferente do `introspection` (keyed pelo próprio token, então cada key tentada
|
|
19
|
+
* cai em bucket distinto), este é keyed por `ctx.request.ip()` — limita o número
|
|
20
|
+
* de tentativas vindas do MESMO IP independentemente de qual key foi usada (M8).
|
|
21
|
+
*/
|
|
22
|
+
adminIp: ThrottleMiddleware;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Service do `@adonisjs/limiter` resolvido de forma preguiçosa. Tipado como `any`
|
|
26
|
+
* de propósito: a lib NÃO depende do limiter em tempo de compilação (peer/opt-in).
|
|
27
|
+
*/
|
|
28
|
+
type LimiterService = any;
|
|
29
|
+
/**
|
|
30
|
+
* Permite reapontar/limpar o loader do limiter (usado em testes).
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export declare function __setLimiterLoaderForTests(fn: (() => Promise<LimiterService | null>) | undefined): void;
|
|
34
|
+
/**
|
|
35
|
+
* Cria os throttles do host-kit a partir da config resolvida.
|
|
36
|
+
* Retorna `undefined` quando rate-limit está desligado (rotas montadas sem throttle).
|
|
37
|
+
*/
|
|
38
|
+
export declare function createAuthThrottles(config: ResolvedRateLimitConfig): AuthThrottles | undefined;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
let limiterServicePromise;
|
|
10
|
+
/**
|
|
11
|
+
* Importa o service do limiter do HOST de forma preguiçosa e fail-safe.
|
|
12
|
+
* Se `@adonisjs/limiter` não estiver instalado/configurado, resolve `null`
|
|
13
|
+
* e o throttle vira no-op (não quebra o boot nem a request).
|
|
14
|
+
*/
|
|
15
|
+
async function loadLimiter() {
|
|
16
|
+
if (!limiterServicePromise) {
|
|
17
|
+
// Indireção via variável: o `@adonisjs/limiter` é peer/opcional e pode não
|
|
18
|
+
// estar instalado na lib, então o specifier não é resolvido em build-time.
|
|
19
|
+
const specifier = '@adonisjs/limiter/services/main';
|
|
20
|
+
limiterServicePromise = import(__rewriteRelativeImportExtension(specifier))
|
|
21
|
+
.then((mod) => mod.default ?? null)
|
|
22
|
+
.catch(() => null);
|
|
23
|
+
}
|
|
24
|
+
return limiterServicePromise;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Permite reapontar/limpar o loader do limiter (usado em testes).
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export function __setLimiterLoaderForTests(fn) {
|
|
31
|
+
if (fn) {
|
|
32
|
+
limiterServicePromise = fn();
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
limiterServicePromise = undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Constrói um middleware de throttle preguiçoso. A configuração do limiter
|
|
40
|
+
* (`allowRequests().every().usingKey()`) só é resolvida na primeira request,
|
|
41
|
+
* porque o service do limiter é importado de forma assíncrona. Se o limiter
|
|
42
|
+
* não existir, o middleware passa adiante sem throttle (fail-safe).
|
|
43
|
+
*/
|
|
44
|
+
function buildThrottle(name, bucket, store, keyOf) {
|
|
45
|
+
let middleware;
|
|
46
|
+
return async (ctx, next) => {
|
|
47
|
+
if (!middleware) {
|
|
48
|
+
const limiter = await loadLimiter();
|
|
49
|
+
if (!limiter) {
|
|
50
|
+
// Limiter indisponível: degrada para no-op (sem quebrar a request).
|
|
51
|
+
middleware = async (_ctx, n) => n();
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
middleware = limiter.define(name, (reqCtx) => {
|
|
55
|
+
let b = limiter.allowRequests(bucket.points).every(bucket.duration);
|
|
56
|
+
if (store)
|
|
57
|
+
b = b.store(store);
|
|
58
|
+
const key = keyOf?.(reqCtx);
|
|
59
|
+
if (key)
|
|
60
|
+
b = b.usingKey(key);
|
|
61
|
+
return b;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return middleware(ctx, next);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Cria os throttles do host-kit a partir da config resolvida.
|
|
70
|
+
* Retorna `undefined` quando rate-limit está desligado (rotas montadas sem throttle).
|
|
71
|
+
*/
|
|
72
|
+
export function createAuthThrottles(config) {
|
|
73
|
+
if (!config.enabled)
|
|
74
|
+
return undefined;
|
|
75
|
+
return {
|
|
76
|
+
// Login/signup/forgot/reset: keyed por IP (default do HttpLimiter).
|
|
77
|
+
login: buildThrottle('authkit_login', config.login, config.store),
|
|
78
|
+
// Introspecção de PAT: keyed pelo bearer secret quando presente, senão por IP.
|
|
79
|
+
introspection: buildThrottle('authkit_pat_introspection', config.introspection, config.store, (ctx) => {
|
|
80
|
+
const auth = ctx.request.header('authorization');
|
|
81
|
+
if (auth && auth.toLowerCase().startsWith('bearer ')) {
|
|
82
|
+
return `bearer:${auth.slice(7).trim()}`;
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}),
|
|
86
|
+
// Admin-api por IP: anti-brute-force REAL da Bearer key (M8). Keyed por IP —
|
|
87
|
+
// tentar muitas keys diferentes do mesmo IP cai no MESMO bucket, ao contrário
|
|
88
|
+
// do `introspection` (bucket por token). Camada adicional, não substitui o
|
|
89
|
+
// throttle de introspection nas rotas que o usam.
|
|
90
|
+
adminIp: buildThrottle('authkit_admin_ip', config.adminIp, config.store, (ctx) => {
|
|
91
|
+
return `admin-ip:${ctx.request.ip?.() ?? 'unknown'}`;
|
|
92
|
+
}),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { Router } from '@adonisjs/core/http';
|
|
2
|
+
import type { AuthSocialConfig, RateLimitConfigInput } from '../define_config.js';
|
|
3
|
+
/** Chave da sessão Adonis que registra o timestamp da última atividade (idle timeout). */
|
|
4
|
+
export declare const ACCOUNT_LAST_SEEN_KEY = "authkit_last_seen";
|
|
5
|
+
/**
|
|
6
|
+
* Guard do console admin (B6). Como o `accountGuard`, é uma closure inline (forma
|
|
7
|
+
* confiável do `.use()` num grupo). Exige:
|
|
8
|
+
* 0. `config.admin.enabled` ligado (senão → 404; ver nota de flag-drift abaixo);
|
|
9
|
+
* 1. sessão de conta ativa (senão → /account/login);
|
|
10
|
+
* 2. a conta logada com pelo menos UMA das `config.admin.roles` nas roles globais
|
|
11
|
+
* (senão → /account/tokens, evitando vazar a existência do /admin).
|
|
12
|
+
* As roles permitidas são resolvidas em runtime do `authkit.server` (config lazy).
|
|
13
|
+
*/
|
|
14
|
+
export declare const adminGuard: (ctx: any, next: () => Promise<void>) => Promise<any>;
|
|
15
|
+
/**
|
|
16
|
+
* Opções de montagem das rotas do host-kit.
|
|
17
|
+
*
|
|
18
|
+
* NOTA (flag-drift): vários campos aqui (`social`, `rateLimit`, `admin`) ESPELHAM
|
|
19
|
+
* o config (`config/authkit.ts`) porque a decisão de MONTAR as rotas acontece em
|
|
20
|
+
* tempo de registro, antes de o config (lazy) resolver. Eles controlam apenas se
|
|
21
|
+
* as rotas existem; a fonte de verdade do COMPORTAMENTO continua sendo o config
|
|
22
|
+
* resolvido. Se um flag aqui divergir do config (ex.: `admin: true` aqui com
|
|
23
|
+
* `admin.enabled: false` no config), os guards das rotas são a rede de segurança
|
|
24
|
+
* (o `adminGuard` 404a quando `config.admin.enabled` é false). Mantenha-os em
|
|
25
|
+
* sincronia; os guards garantem que a divergência não vire um bypass.
|
|
26
|
+
*/
|
|
27
|
+
export interface AuthHostOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Onde o provider OIDC é montado. Deve casar com o final do issuer. OPCIONAL:
|
|
30
|
+
* quando omitido, vem do `config/authkit.ts` (lido no boot); default `/oidc`.
|
|
31
|
+
*/
|
|
32
|
+
mountPath?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Login social opt-in; quando presente, monta as rotas sociais (usam ctx.ally).
|
|
35
|
+
* Necessário aqui (e não só no config) porque a decisão de montar as rotas é
|
|
36
|
+
* tomada em tempo de registro, antes do config (lazy) resolver.
|
|
37
|
+
*/
|
|
38
|
+
social?: AuthSocialConfig;
|
|
39
|
+
/**
|
|
40
|
+
* Rate-limiting (anti-brute-force) das rotas sensíveis. Necessário aqui (e não
|
|
41
|
+
* só no config) porque a aplicação do throttle acontece em tempo de registro de
|
|
42
|
+
* rota. Ligado por default (mesma resolução do config). Espelhe o `rateLimit` de
|
|
43
|
+
* config/authkit.ts. Se `@adonisjs/limiter` não estiver configurado no host
|
|
44
|
+
* (config/limiter.ts), o throttle vira no-op (fail-safe).
|
|
45
|
+
*/
|
|
46
|
+
rateLimit?: RateLimitConfigInput;
|
|
47
|
+
/**
|
|
48
|
+
* Console admin opt-in (B6).
|
|
49
|
+
*
|
|
50
|
+
* - `true` → comportamento padrão: monta as rotas sob o prefixo `/admin` (back-compat total);
|
|
51
|
+
* modo UI `'react'` (SPA self-contained).
|
|
52
|
+
* - `{ prefix?: string }` → prefixo customizado.
|
|
53
|
+
* O prefixo é normalizado: começa com `/`, sem trailing slash.
|
|
54
|
+
* Quando `prefix` é omitido ou vazio, usa o default `/admin`.
|
|
55
|
+
*
|
|
56
|
+
* Necessário aqui (e não só no config) porque a decisão de montar as rotas é
|
|
57
|
+
* tomada em tempo de registro, antes do config (lazy) resolver.
|
|
58
|
+
* Espelhe o `admin.enabled` de config/authkit.ts.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Prefixo padrão
|
|
62
|
+
* registerAuthHost(router, { mountPath: '/oidc', admin: true })
|
|
63
|
+
*
|
|
64
|
+
* // Prefixo customizado — console em /auth/admin
|
|
65
|
+
* registerAuthHost(router, { mountPath: '/oidc', admin: { prefix: '/auth/admin' } })
|
|
66
|
+
*/
|
|
67
|
+
admin?: boolean | {
|
|
68
|
+
prefix?: string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Admin REST API opt-in (R6).
|
|
72
|
+
*
|
|
73
|
+
* - `true` → comportamento padrão: monta o grupo sob `/api/authkit/v1` (back-compat total).
|
|
74
|
+
* - `{ prefix?: string }` → monta sob o prefixo fornecido, e.g. `{ prefix: '/authkit/api' }`.
|
|
75
|
+
* O prefixo é normalizado: começa com `/`, sem trailing slash.
|
|
76
|
+
* Quando `prefix` é omitido ou vazio, usa o default `/api/authkit/v1`.
|
|
77
|
+
*
|
|
78
|
+
* Necessário aqui (e não só no config) porque a decisão de montar as rotas é
|
|
79
|
+
* tomada em tempo de registro, antes do config (lazy) resolver.
|
|
80
|
+
* Espelhe o `adminApi.enabled` de config/authkit.ts.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* // Prefixo padrão (back-compat)
|
|
84
|
+
* registerAuthHost(router, { mountPath: '/oidc', adminApi: true })
|
|
85
|
+
*
|
|
86
|
+
* // Prefixo customizado — API em /authkit/api
|
|
87
|
+
* registerAuthHost(router, { mountPath: '/oidc', adminApi: { prefix: '/authkit/api' } })
|
|
88
|
+
*/
|
|
89
|
+
adminApi?: boolean | {
|
|
90
|
+
prefix?: string;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Monta todas as rotas do host-kit do Authorization Server numa chamada.
|
|
95
|
+
* Substitui registerOidcRoutes + o hand-wiring do start/routes.ts do host.
|
|
96
|
+
*/
|
|
97
|
+
export declare function registerAuthHost(router: Router, opts?: AuthHostOptions): void;
|