@adonis-agora/authkit-server 0.47.0 → 0.48.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/build/commands/clients_create.js +4 -4
- package/build/commands/configure.js +3 -2
- package/build/commands/doctor.js +8 -5
- package/build/commands/eject.js +1 -1
- package/build/commands/expire_scan.js +7 -5
- package/build/commands/import_users.js +1 -1
- package/build/commands/keys_rotate.js +7 -4
- package/build/host/views/account/apps.edge +5 -5
- package/build/host/views/account/login.edge +1 -1
- package/build/host/views/account/mfa.edge +7 -7
- package/build/host/views/account/orgs.edge +5 -5
- package/build/host/views/account/security.edge +10 -10
- package/build/host/views/account/tokens.edge +5 -5
- package/build/index.d.ts +7 -7
- package/build/index.js +5 -5
- package/build/providers/authkit_server_provider.d.ts +2 -2
- package/build/providers/authkit_server_provider.js +20 -11
- package/build/services/main.d.ts +1 -1
- package/build/services/main.js +2 -2
- package/build/src/accounts/lucid_account_store.d.ts +3 -3
- package/build/src/accounts/lucid_account_store.js +6 -8
- package/build/src/accounts/lucid_store/core.js +1 -1
- package/build/src/accounts/lucid_store/mfa.js +1 -1
- package/build/src/accounts/lucid_store/organizations.js +2 -4
- package/build/src/accounts/lucid_store/password_hygiene.js +1 -4
- package/build/src/accounts/lucid_store/shared.d.ts +1 -1
- package/build/src/accounts/lucid_stores.d.ts +3 -3
- package/build/src/accounts/lucid_stores.js +2 -2
- package/build/src/adapters/database_adapter.js +3 -1
- package/build/src/adapters/factory.js +1 -1
- package/build/src/adapters/redis_adapter.js +2 -1
- package/build/src/commands/expire_scan_command.js +19 -5
- package/build/src/commands/settings_commands.js +22 -5
- package/build/src/define_config.d.ts +20 -20
- package/build/src/define_config.js +62 -67
- package/build/src/doctor/checks.js +45 -20
- package/build/src/events/dispatcher.d.ts +1 -1
- package/build/src/events/dispatcher.js +10 -10
- package/build/src/host/account_api/account_api_controller.js +95 -39
- package/build/src/host/account_deletion_ops.d.ts +4 -4
- package/build/src/host/account_deletion_ops.js +5 -5
- package/build/src/host/account_deletion_service.d.ts +2 -2
- package/build/src/host/account_deletion_service.js +2 -2
- package/build/src/host/account_export_service.d.ts +1 -1
- package/build/src/host/account_export_service.js +4 -6
- package/build/src/host/account_home.d.ts +0 -8
- package/build/src/host/account_home.js +6 -4
- package/build/src/host/account_login_url.d.ts +6 -3
- package/build/src/host/account_login_url.js +16 -8
- package/build/src/host/account_paths.d.ts +120 -0
- package/build/src/host/account_paths.js +161 -0
- package/build/src/host/admin_api/admin_orgs_service.d.ts +2 -2
- package/build/src/host/admin_api/admin_orgs_service.js +3 -2
- package/build/src/host/admin_api/admin_users_service.d.ts +12 -12
- package/build/src/host/admin_api/admin_users_service.js +20 -20
- package/build/src/host/admin_api/api_clients_controller.js +2 -2
- package/build/src/host/admin_api/api_misc_controller.js +2 -2
- package/build/src/host/admin_api/api_orgs_controller.js +3 -3
- package/build/src/host/admin_api/api_settings_controller.js +11 -5
- package/build/src/host/admin_api/api_users_controller.d.ts +2 -2
- package/build/src/host/admin_api/api_users_controller.js +37 -38
- package/build/src/host/admin_api/dto.d.ts +4 -4
- package/build/src/host/admin_clients_service.js +5 -4
- package/build/src/host/admin_console/admin_shell_controller.js +4 -2
- package/build/src/host/admin_console/console_audit_controller.js +1 -1
- package/build/src/host/admin_console/console_clients_controller.js +5 -3
- package/build/src/host/admin_console/console_impersonation_controller.js +1 -1
- package/build/src/host/admin_console/console_keys_controller.js +2 -4
- package/build/src/host/admin_console/console_orgs_controller.js +3 -3
- package/build/src/host/admin_console/console_roles_controller.js +30 -12
- package/build/src/host/admin_console/console_sessions_controller.js +3 -3
- package/build/src/host/admin_console/console_settings_controller.js +11 -5
- package/build/src/host/admin_console/console_users_controller.d.ts +2 -2
- package/build/src/host/admin_console/console_users_controller.js +46 -47
- package/build/src/host/admin_prefix.js +2 -2
- package/build/src/host/admin_sessions_service.js +1 -3
- package/build/src/host/adonis_auth_sync.d.ts +1 -1
- package/build/src/host/adonis_auth_user_provider.d.ts +1 -1
- package/build/src/host/app_key.js +1 -1
- package/build/src/host/avatar_storage.js +1 -3
- package/build/src/host/config_locks.js +1 -3
- package/build/src/host/console_session.js +1 -1
- package/build/src/host/controllers/account_apps_controller.js +3 -2
- package/build/src/host/controllers/account_confirm_controller.js +2 -6
- package/build/src/host/controllers/account_mfa_controller.js +63 -12
- package/build/src/host/controllers/account_orgs_controller.js +47 -27
- package/build/src/host/controllers/account_security_controller.d.ts +2 -2
- package/build/src/host/controllers/account_security_controller.js +114 -115
- package/build/src/host/controllers/account_session_controller.js +5 -5
- package/build/src/host/controllers/account_tokens_controller.js +3 -2
- package/build/src/host/controllers/interaction_controller.js +59 -22
- package/build/src/host/controllers/registration_controller.js +28 -13
- package/build/src/host/default_mailer.js +11 -7
- package/build/src/host/durable/account_deletion_workflow.d.ts +2 -2
- package/build/src/host/durable/account_deletion_workflow.js +14 -14
- package/build/src/host/durable/account_export_workflow.d.ts +2 -2
- package/build/src/host/durable/account_export_workflow.js +12 -12
- package/build/src/host/durable/index.d.ts +5 -5
- package/build/src/host/durable/index.js +6 -6
- package/build/src/host/i18n.d.ts +1376 -1376
- package/build/src/host/i18n.js +1380 -1380
- package/build/src/host/impersonation.js +1 -7
- package/build/src/host/key_rotation_actions.d.ts +1 -1
- package/build/src/host/login_attempt.js +35 -6
- package/build/src/host/login_notify.js +1 -1
- package/build/src/host/otp_lockout.js +1 -3
- package/build/src/host/rate_limit.js +1 -1
- package/build/src/host/register_auth_host.d.ts +30 -0
- package/build/src/host/register_auth_host.js +120 -74
- package/build/src/host/renderers/edge_renderer.js +15 -2
- package/build/src/host/renderers/inertia_renderer.d.ts +9 -1
- package/build/src/host/renderers/inertia_renderer.js +9 -1
- package/build/src/host/runtime_settings.js +1 -1
- package/build/src/host/runtime_toggles.d.ts +3 -3
- package/build/src/host/runtime_toggles.js +69 -24
- package/build/src/host/security_notice_service.d.ts +1 -1
- package/build/src/host/security_notice_service.js +1 -1
- package/build/src/host/session_context.js +1 -1
- package/build/src/host/sudo/index.d.ts +3 -3
- package/build/src/host/sudo/index.js +3 -3
- package/build/src/host/sudo/methods/magic_link.js +6 -5
- package/build/src/host/sudo/methods/passkey.js +7 -4
- package/build/src/host/sudo/methods/password.js +8 -3
- package/build/src/host/sudo/runtime.js +6 -13
- package/build/src/host/sudo_mode.js +3 -2
- package/build/src/host/ui-dist/assets/index-BQoTDiLV.js +137 -0
- package/build/src/host/ui-dist/index.html +1 -1
- package/build/src/keys/jwks_manager.js +1 -1
- package/build/src/keys/keystore.js +1 -1
- package/build/src/keys/keystore_manager.d.ts +2 -2
- package/build/src/keys/keystore_manager.js +2 -2
- package/build/src/keys/keystore_vault.js +8 -4
- package/build/src/mixins/with_audit_log.d.ts +1 -1
- package/build/src/mixins/with_auth_user.d.ts +1 -1
- package/build/src/mixins/with_auth_user.js +1 -1
- package/build/src/mixins/with_credentials.d.ts +1 -1
- package/build/src/mixins/with_mfa.d.ts +1 -1
- package/build/src/mixins/with_personal_access_token.d.ts +1 -1
- package/build/src/mixins/with_provider_identity.d.ts +1 -1
- package/build/src/mixins/with_webauthn_credential.d.ts +1 -1
- package/build/src/observability/diagnostics_bridge.js +2 -2
- package/build/src/observability/metrics_service.js +1 -1
- package/build/src/observability/telescope/data_providers.d.ts +1 -1
- package/build/src/observability/telescope/data_providers.js +29 -43
- package/build/src/observability/telescope/extension.d.ts +1 -1
- package/build/src/observability/telescope/extension.js +58 -58
- package/build/src/observability/telescope/index.d.ts +2 -2
- package/build/src/observability/telescope/index.js +2 -2
- package/build/src/observability/wire_provider_events.d.ts +1 -1
- package/build/src/observability/wire_provider_events.js +11 -11
- package/build/src/password/common_passwords.js +1 -1
- package/build/src/password/password_manager.d.ts +1 -1
- package/build/src/password/password_manager.js +4 -4
- package/build/src/pat/lucid_pat_store.js +2 -6
- package/build/src/pat/pat_tokens.js +1 -1
- package/build/src/provider/interaction_actions.js +1 -1
- package/build/src/provider/key_rotation_scheduler.js +3 -1
- package/build/src/provider/logout_sources.js +2 -8
- package/build/src/provider/oidc_service.d.ts +2 -2
- package/build/src/provider/oidc_service.js +22 -14
- package/build/src/provider/single_flight_lock.js +1 -3
- package/build/src/provider/token_exchange.d.ts +1 -1
- package/build/src/schema/ensure.js +3 -1
- package/build/stubs/ui/react/components/auth_shell.tsx +19 -19
- package/build/stubs/ui/react/pages/account/login.tsx +6 -7
- package/build/stubs/ui/react/pages/account/mfa.tsx +16 -15
- package/build/stubs/ui/react/pages/account/tokens.tsx +27 -17
- package/build/stubs/ui/react/pages/consent.tsx +12 -12
- package/build/stubs/ui/react/pages/forgot.tsx +7 -7
- package/build/stubs/ui/react/pages/login.tsx +22 -24
- package/build/stubs/ui/react/pages/mfa-challenge.tsx +9 -10
- package/build/stubs/ui/react/pages/reset.tsx +10 -10
- package/build/stubs/ui/react/pages/signup.tsx +30 -16
- package/build/stubs/ui/react/pages/verify-email.tsx +6 -6
- package/package.json +1 -1
- package/stubs/main.ts +2 -2
- package/stubs/ui/react/components/auth_shell.tsx +19 -19
- package/stubs/ui/react/pages/account/login.tsx +6 -7
- package/stubs/ui/react/pages/account/mfa.tsx +16 -15
- package/stubs/ui/react/pages/account/tokens.tsx +27 -17
- package/stubs/ui/react/pages/consent.tsx +12 -12
- package/stubs/ui/react/pages/forgot.tsx +7 -7
- package/stubs/ui/react/pages/login.tsx +22 -24
- package/stubs/ui/react/pages/mfa-challenge.tsx +9 -10
- package/stubs/ui/react/pages/reset.tsx +10 -10
- package/stubs/ui/react/pages/signup.tsx +30 -16
- package/stubs/ui/react/pages/verify-email.tsx +6 -6
- package/build/src/host/ui-dist/assets/index-BmI_J87g.js +0 -137
|
@@ -56,7 +56,7 @@ export const SETTING_KEYS = {
|
|
|
56
56
|
* FAIL-SAFE: `getSetting` nunca lança (contrato do RuntimeSettings). Se
|
|
57
57
|
* retornar null, usamos configDefault.
|
|
58
58
|
*/
|
|
59
|
-
export async function resolveEffectiveRegistration(configDefault
|
|
59
|
+
export async function resolveEffectiveRegistration(configDefault, settings) {
|
|
60
60
|
const raw = await settings.getSetting(SETTING_KEYS.REGISTRATION);
|
|
61
61
|
if (raw === null || raw === undefined)
|
|
62
62
|
return configDefault;
|
|
@@ -74,7 +74,7 @@ export async function resolveEffectiveRegistration(configDefault = true, setting
|
|
|
74
74
|
* - setting presente → sobrescreve.
|
|
75
75
|
* - setting ausente/inválido/erro → usa configDefault.
|
|
76
76
|
*/
|
|
77
|
-
export async function resolveEffectiveRequireVerifiedEmail(configDefault
|
|
77
|
+
export async function resolveEffectiveRequireVerifiedEmail(configDefault, settings) {
|
|
78
78
|
const raw = await settings.getSetting(SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
|
|
79
79
|
if (raw === null || raw === undefined)
|
|
80
80
|
return configDefault;
|
|
@@ -89,7 +89,7 @@ export async function resolveEffectiveRequireVerifiedEmail(configDefault = false
|
|
|
89
89
|
*
|
|
90
90
|
* FAIL-SAFE: qualquer erro → `{ enabled: configDefault, graceDays: 0 }`.
|
|
91
91
|
*/
|
|
92
|
-
export async function resolveEffectiveRequireVerifiedEmailFull(configDefault
|
|
92
|
+
export async function resolveEffectiveRequireVerifiedEmailFull(configDefault, settings) {
|
|
93
93
|
try {
|
|
94
94
|
const raw = await settings.getSetting(SETTING_KEYS.REQUIRE_VERIFIED_EMAIL);
|
|
95
95
|
if (raw === null || raw === undefined)
|
|
@@ -229,7 +229,11 @@ export async function resolveEffectiveAuthMethods(settings, capabilities = {}) {
|
|
|
229
229
|
* FAIL-SAFE: qualquer erro → defaults (enabled true, 24h, requirePassword true).
|
|
230
230
|
*/
|
|
231
231
|
export async function resolveEffectiveEmailChange(settings) {
|
|
232
|
-
const defaults = {
|
|
232
|
+
const defaults = {
|
|
233
|
+
enabled: true,
|
|
234
|
+
ttlHours: 24,
|
|
235
|
+
requirePassword: true,
|
|
236
|
+
};
|
|
233
237
|
try {
|
|
234
238
|
const raw = await settings.getSetting(SETTING_KEYS.EMAIL_CHANGE);
|
|
235
239
|
if (raw === null || raw === undefined)
|
|
@@ -344,10 +348,16 @@ export async function resolveEffectiveSessionPolicy(settings, configDefaultSessi
|
|
|
344
348
|
const s = raw;
|
|
345
349
|
return {
|
|
346
350
|
rememberEnabled: typeof s.rememberEnabled === 'boolean' ? s.rememberEnabled : defaults.rememberEnabled,
|
|
347
|
-
rememberDays: typeof s.rememberDays === 'number' && s.rememberDays >= 1
|
|
348
|
-
|
|
351
|
+
rememberDays: typeof s.rememberDays === 'number' && s.rememberDays >= 1
|
|
352
|
+
? Math.floor(s.rememberDays)
|
|
353
|
+
: defaults.rememberDays,
|
|
354
|
+
defaultSessionHours: typeof s.defaultSessionHours === 'number' && s.defaultSessionHours >= 1
|
|
355
|
+
? Math.floor(s.defaultSessionHours)
|
|
356
|
+
: defaults.defaultSessionHours,
|
|
349
357
|
singleSession: typeof s.singleSession === 'boolean' ? s.singleSession : defaults.singleSession,
|
|
350
|
-
idleTimeoutMinutes: typeof s.idleTimeoutMinutes === 'number' && s.idleTimeoutMinutes >= 0
|
|
358
|
+
idleTimeoutMinutes: typeof s.idleTimeoutMinutes === 'number' && s.idleTimeoutMinutes >= 0
|
|
359
|
+
? Math.floor(s.idleTimeoutMinutes)
|
|
360
|
+
: defaults.idleTimeoutMinutes,
|
|
351
361
|
};
|
|
352
362
|
}
|
|
353
363
|
catch {
|
|
@@ -370,7 +380,9 @@ export async function resolveEffectivePasswordExpiration(settings) {
|
|
|
370
380
|
const s = raw;
|
|
371
381
|
return {
|
|
372
382
|
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
373
|
-
maxAgeDays: typeof s.maxAgeDays === 'number' && s.maxAgeDays >= 1
|
|
383
|
+
maxAgeDays: typeof s.maxAgeDays === 'number' && s.maxAgeDays >= 1
|
|
384
|
+
? Math.floor(s.maxAgeDays)
|
|
385
|
+
: defaults.maxAgeDays,
|
|
374
386
|
};
|
|
375
387
|
}
|
|
376
388
|
catch {
|
|
@@ -407,10 +419,18 @@ export async function resolveEffectiveLockout(settings, configDefault = {}) {
|
|
|
407
419
|
const s = raw;
|
|
408
420
|
return {
|
|
409
421
|
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
410
|
-
maxAttempts: typeof s.maxAttempts === 'number' && s.maxAttempts >= 1
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
422
|
+
maxAttempts: typeof s.maxAttempts === 'number' && s.maxAttempts >= 1
|
|
423
|
+
? Math.floor(s.maxAttempts)
|
|
424
|
+
: defaults.maxAttempts,
|
|
425
|
+
windowSec: typeof s.windowSec === 'number' && s.windowSec >= 1
|
|
426
|
+
? Math.floor(s.windowSec)
|
|
427
|
+
: defaults.windowSec,
|
|
428
|
+
baseLockoutSec: typeof s.baseLockoutSec === 'number' && s.baseLockoutSec >= 1
|
|
429
|
+
? Math.floor(s.baseLockoutSec)
|
|
430
|
+
: defaults.baseLockoutSec,
|
|
431
|
+
maxLockoutSec: typeof s.maxLockoutSec === 'number' && s.maxLockoutSec >= 1
|
|
432
|
+
? Math.floor(s.maxLockoutSec)
|
|
433
|
+
: defaults.maxLockoutSec,
|
|
414
434
|
};
|
|
415
435
|
}
|
|
416
436
|
catch {
|
|
@@ -450,12 +470,20 @@ export async function resolveEffectiveRateLimit(settings, configDefault = {}) {
|
|
|
450
470
|
const s = raw;
|
|
451
471
|
return {
|
|
452
472
|
login: {
|
|
453
|
-
points: typeof s.login?.points === 'number' && s.login.points >= 1
|
|
454
|
-
|
|
473
|
+
points: typeof s.login?.points === 'number' && s.login.points >= 1
|
|
474
|
+
? Math.floor(s.login.points)
|
|
475
|
+
: defaults.login.points,
|
|
476
|
+
duration: typeof s.login?.duration === 'string' && s.login.duration.trim()
|
|
477
|
+
? s.login.duration.trim()
|
|
478
|
+
: defaults.login.duration,
|
|
455
479
|
},
|
|
456
480
|
introspection: {
|
|
457
|
-
points: typeof s.introspection?.points === 'number' && s.introspection.points >= 1
|
|
458
|
-
|
|
481
|
+
points: typeof s.introspection?.points === 'number' && s.introspection.points >= 1
|
|
482
|
+
? Math.floor(s.introspection.points)
|
|
483
|
+
: defaults.introspection.points,
|
|
484
|
+
duration: typeof s.introspection?.duration === 'string' && s.introspection.duration.trim()
|
|
485
|
+
? s.introspection.duration.trim()
|
|
486
|
+
: defaults.introspection.duration,
|
|
459
487
|
},
|
|
460
488
|
};
|
|
461
489
|
}
|
|
@@ -496,7 +524,9 @@ export async function resolveEffectivePasswordPolicy(settings, configDefault = {
|
|
|
496
524
|
return defaults;
|
|
497
525
|
const s = raw;
|
|
498
526
|
return {
|
|
499
|
-
minLength: typeof s.minLength === 'number' && s.minLength >= 1
|
|
527
|
+
minLength: typeof s.minLength === 'number' && s.minLength >= 1
|
|
528
|
+
? Math.floor(s.minLength)
|
|
529
|
+
: defaults.minLength,
|
|
500
530
|
requireUppercase: typeof s.requireUppercase === 'boolean' ? s.requireUppercase : defaults.requireUppercase,
|
|
501
531
|
requireLowercase: typeof s.requireLowercase === 'boolean' ? s.requireLowercase : defaults.requireLowercase,
|
|
502
532
|
requireNumbers: typeof s.requireNumbers === 'boolean' ? s.requireNumbers : defaults.requireNumbers,
|
|
@@ -583,9 +613,15 @@ export async function resolveEffectiveTokenTtl(settings, configDefault = {}) {
|
|
|
583
613
|
return defaults;
|
|
584
614
|
const s = raw;
|
|
585
615
|
return {
|
|
586
|
-
accessTokenSec: typeof s.accessTokenSec === 'number' && s.accessTokenSec >= 1
|
|
587
|
-
|
|
588
|
-
|
|
616
|
+
accessTokenSec: typeof s.accessTokenSec === 'number' && s.accessTokenSec >= 1
|
|
617
|
+
? Math.floor(s.accessTokenSec)
|
|
618
|
+
: defaults.accessTokenSec,
|
|
619
|
+
idTokenSec: typeof s.idTokenSec === 'number' && s.idTokenSec >= 1
|
|
620
|
+
? Math.floor(s.idTokenSec)
|
|
621
|
+
: defaults.idTokenSec,
|
|
622
|
+
refreshTokenSec: typeof s.refreshTokenSec === 'number' && s.refreshTokenSec >= 1
|
|
623
|
+
? Math.floor(s.refreshTokenSec)
|
|
624
|
+
: defaults.refreshTokenSec,
|
|
589
625
|
};
|
|
590
626
|
}
|
|
591
627
|
catch {
|
|
@@ -652,7 +688,10 @@ export async function resolveEffectiveRolesCatalog(settings, orgId) {
|
|
|
652
688
|
return null;
|
|
653
689
|
// Filtra entradas válidas (name deve ser string não-vazia).
|
|
654
690
|
const entries = s.roles
|
|
655
|
-
.filter((r) => typeof r === 'object' &&
|
|
691
|
+
.filter((r) => typeof r === 'object' &&
|
|
692
|
+
r !== null &&
|
|
693
|
+
typeof r.name === 'string' &&
|
|
694
|
+
r.name.trim().length > 0)
|
|
656
695
|
.map((r) => ({
|
|
657
696
|
name: r.name.trim(),
|
|
658
697
|
...(typeof r.description === 'string' && r.description.trim().length > 0
|
|
@@ -720,7 +759,9 @@ export async function resolveEffectiveOrganizationsPolicy(settings, configDefaul
|
|
|
720
759
|
}
|
|
721
760
|
return {
|
|
722
761
|
allowSelfCreate: typeof s.allowSelfCreate === 'boolean' ? s.allowSelfCreate : defaults.allowSelfCreate,
|
|
723
|
-
invitationTtlHours: typeof s.invitationTtlHours === 'number' && s.invitationTtlHours >= 1
|
|
762
|
+
invitationTtlHours: typeof s.invitationTtlHours === 'number' && s.invitationTtlHours >= 1
|
|
763
|
+
? Math.floor(s.invitationTtlHours)
|
|
764
|
+
: defaults.invitationTtlHours,
|
|
724
765
|
roles,
|
|
725
766
|
};
|
|
726
767
|
}
|
|
@@ -798,8 +839,12 @@ export async function resolveEffectiveAccountExpiration(settings) {
|
|
|
798
839
|
const s = raw;
|
|
799
840
|
return {
|
|
800
841
|
enabled: typeof s.enabled === 'boolean' ? s.enabled : defaults.enabled,
|
|
801
|
-
inactiveDays: typeof s.inactiveDays === 'number' && s.inactiveDays >= 1
|
|
802
|
-
|
|
842
|
+
inactiveDays: typeof s.inactiveDays === 'number' && s.inactiveDays >= 1
|
|
843
|
+
? Math.floor(s.inactiveDays)
|
|
844
|
+
: defaults.inactiveDays,
|
|
845
|
+
warnDays: typeof s.warnDays === 'number' && s.warnDays >= 0
|
|
846
|
+
? Math.floor(s.warnDays)
|
|
847
|
+
: defaults.warnDays,
|
|
803
848
|
};
|
|
804
849
|
}
|
|
805
850
|
catch {
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* O hook `mail.onSecurityNotice` do config tem prioridade sobre o mailer default.
|
|
8
8
|
*/
|
|
9
9
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
10
|
-
import type { MailHooks } from '../define_config.js';
|
|
11
10
|
import type { AuditSink } from '../audit/audit_sink.js';
|
|
11
|
+
import type { MailHooks } from '../define_config.js';
|
|
12
12
|
import type { SecurityNotificationKind } from './runtime_toggles.js';
|
|
13
13
|
/**
|
|
14
14
|
* Contexto para disparo de uma notificação de segurança.
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Respeita a setting `security_notifications` em `auth_settings` (enabled + kinds).
|
|
7
7
|
* O hook `mail.onSecurityNotice` do config tem prioridade sobre o mailer default.
|
|
8
8
|
*/
|
|
9
|
+
import { sendSecurityNoticeEmail } from './default_mailer.js';
|
|
9
10
|
import { resolveRuntimeSettings } from './runtime_settings.js';
|
|
10
11
|
import { resolveEffectiveSecurityNotifications } from './runtime_toggles.js';
|
|
11
|
-
import { sendSecurityNoticeEmail } from './default_mailer.js';
|
|
12
12
|
/**
|
|
13
13
|
* Despacha uma notificação de segurança, se habilitada e o kind for um dos
|
|
14
14
|
* configurados. Best-effort: qualquer falha é ignorada silenciosamente (logged).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseUserAgent } from './user_agent.js';
|
|
2
1
|
import { resolveGeoSafe } from './geo.js';
|
|
2
|
+
import { parseUserAgent } from './user_agent.js';
|
|
3
3
|
/**
|
|
4
4
|
* ENRIQUECE sessões ativas com contexto de dispositivo (user-agent → browser/SO),
|
|
5
5
|
* IP e localização, SEM tocar no payload da `Session` do oidc-provider (que não é
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { password } from './methods/password.js';
|
|
2
|
-
import { passkey } from './methods/passkey.js';
|
|
3
|
-
import { oidcStepUp } from './methods/oidc_step_up.js';
|
|
4
1
|
import { magicLink } from './methods/magic_link.js';
|
|
2
|
+
import { oidcStepUp } from './methods/oidc_step_up.js';
|
|
3
|
+
import { passkey } from './methods/passkey.js';
|
|
4
|
+
import { password } from './methods/password.js';
|
|
5
5
|
/**
|
|
6
6
|
* Métodos de confirmação de identidade (sudo mode), no mesmo padrão de factory
|
|
7
7
|
* usado em `stores.*` e `retrievers.*` das libs irmãs.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { password } from './methods/password.js';
|
|
2
|
-
import { passkey } from './methods/passkey.js';
|
|
3
|
-
import { oidcStepUp } from './methods/oidc_step_up.js';
|
|
4
1
|
import { magicLink } from './methods/magic_link.js';
|
|
2
|
+
import { oidcStepUp } from './methods/oidc_step_up.js';
|
|
3
|
+
import { passkey } from './methods/passkey.js';
|
|
4
|
+
import { password } from './methods/password.js';
|
|
5
5
|
/**
|
|
6
6
|
* Métodos de confirmação de identidade (sudo mode), no mesmo padrão de factory
|
|
7
7
|
* usado em `stores.*` e `retrievers.*` das libs irmãs.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import { accountPath } from '../../account_paths.js';
|
|
2
3
|
import { translate } from '../../i18n.js';
|
|
3
4
|
import { isSudoMethodEnabled } from '../runtime.js';
|
|
4
5
|
/** Token de sudo pendente, guardado na sessão que o pediu. */
|
|
@@ -105,11 +106,11 @@ export function magicLink() {
|
|
|
105
106
|
return {
|
|
106
107
|
labelKey: 'account.confirm.method.magic_link',
|
|
107
108
|
kind: 'action',
|
|
108
|
-
endpoint: '
|
|
109
|
+
endpoint: `${accountPath('confirm')}/magic-link`,
|
|
109
110
|
};
|
|
110
111
|
},
|
|
111
112
|
register(router, h) {
|
|
112
|
-
router.post('
|
|
113
|
+
router.post(`${accountPath('confirm')}/magic-link`, async (ctx) => {
|
|
113
114
|
const c = await h.contextFrom(ctx);
|
|
114
115
|
// ANTES de qualquer coisa: o host desligou este método? A rota é montada
|
|
115
116
|
// incondicionalmente, então só o handler faz `config.sudo.methods` valer.
|
|
@@ -129,7 +130,7 @@ export function magicLink() {
|
|
|
129
130
|
return h.fail(c, 'account.confirm.error');
|
|
130
131
|
const qs = c.returnTo ? `?return_to=${encodeURIComponent(c.returnTo)}` : '';
|
|
131
132
|
const token = issueSudoLinkToken(c);
|
|
132
|
-
const path =
|
|
133
|
+
const path = `${accountPath('confirm')}/magic-link/${token}${qs}`;
|
|
133
134
|
const origin = requestOrigin(ctx);
|
|
134
135
|
try {
|
|
135
136
|
await onSudoLink({ email: c.account.email, sudoUrl: origin ? `${origin}${path}` : path });
|
|
@@ -145,9 +146,9 @@ export function magicLink() {
|
|
|
145
146
|
// `translate(...)` em `confirmError`, e a tela leria dois formatos
|
|
146
147
|
// diferentes se este aqui mandasse a chave.
|
|
147
148
|
ctx.session.flash('confirmNotice', translate(c.cfg.messages, 'account.confirm.magic_link_sent'));
|
|
148
|
-
return ctx.response.redirect(
|
|
149
|
+
return ctx.response.redirect(`${accountPath('confirm')}${qs}`);
|
|
149
150
|
});
|
|
150
|
-
router.get('
|
|
151
|
+
router.get(`${accountPath('confirm')}/magic-link/:token`, async (ctx) => {
|
|
151
152
|
const c = await h.contextFrom(ctx);
|
|
152
153
|
if (!isSudoMethodEnabled(c.cfg, 'magic-link'))
|
|
153
154
|
return h.fail(c, 'account.confirm.error');
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { supportsPasskeys } from '../../../accounts/account_store.js';
|
|
2
|
+
import { accountPath } from '../../account_paths.js';
|
|
2
3
|
import { translate } from '../../i18n.js';
|
|
3
4
|
import { isSudoMethodEnabled } from '../runtime.js';
|
|
4
5
|
/** Chave de sessão do challenge — preservada do controller original. */
|
|
@@ -45,18 +46,20 @@ export function passkey() {
|
|
|
45
46
|
// que faz a tela rodar o handshake — e o endpoint de options ela deriva
|
|
46
47
|
// daqui (`${endpoint}/options`), sem conhecer o id 'passkey'.
|
|
47
48
|
kind: 'webauthn',
|
|
48
|
-
endpoint: '
|
|
49
|
+
endpoint: `${accountPath('confirm')}/passkey`,
|
|
49
50
|
};
|
|
50
51
|
},
|
|
51
52
|
register(router, h) {
|
|
52
|
-
router.post('
|
|
53
|
+
router.post(`${accountPath('confirm')}/passkey/options`, async (ctx) => {
|
|
53
54
|
const c = await h.contextFrom(ctx);
|
|
54
55
|
// i18n: mesma chave usada pelo controller original — hosts com catálogo
|
|
55
56
|
// customizado (ex.: pt-BR) não podem perder a mensagem localizada aqui.
|
|
56
57
|
// Reusada nas TRÊS recusas abaixo de propósito: "método desligado",
|
|
57
58
|
// "conta inexistente" e "sem passkey" ficam indistinguíveis para o
|
|
58
59
|
// chamador.
|
|
59
|
-
const deny = () => ctx.response.notFound({
|
|
60
|
+
const deny = () => ctx.response.notFound({
|
|
61
|
+
message: translate(c.cfg.messages, 'errors.no_passkey_registered'),
|
|
62
|
+
});
|
|
60
63
|
// ANTES de qualquer coisa: o host desligou este método? A rota é montada
|
|
61
64
|
// incondicionalmente, então só o handler faz `config.sudo.methods` valer.
|
|
62
65
|
if (!isSudoMethodEnabled(c.cfg, 'passkey'))
|
|
@@ -79,7 +82,7 @@ export function passkey() {
|
|
|
79
82
|
ctx.session.put(CONFIRM_PASSKEY_CHALLENGE_ACCOUNT_KEY, c.accountId);
|
|
80
83
|
return generated.options;
|
|
81
84
|
});
|
|
82
|
-
router.post('
|
|
85
|
+
router.post(`${accountPath('confirm')}/passkey`, async (ctx) => {
|
|
83
86
|
const c = await h.contextFrom(ctx);
|
|
84
87
|
// Método desligado pelo host → mesma resposta de uma assertion inválida
|
|
85
88
|
// (redirect + flash), para não vazar a config.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { accountPath } from '../../account_paths.js';
|
|
1
2
|
import { isSudoMethodEnabled } from '../runtime.js';
|
|
2
3
|
/**
|
|
3
4
|
* Confirmação por senha — o método histórico.
|
|
@@ -60,14 +61,18 @@ export function password() {
|
|
|
60
61
|
return {
|
|
61
62
|
labelKey: 'account.confirm.method.password',
|
|
62
63
|
kind: 'form',
|
|
63
|
-
endpoint: '
|
|
64
|
+
endpoint: accountPath('confirm'),
|
|
64
65
|
fields: [
|
|
65
|
-
{
|
|
66
|
+
{
|
|
67
|
+
name: 'password',
|
|
68
|
+
type: 'password',
|
|
69
|
+
labelKey: 'account.confirm.password_label',
|
|
70
|
+
},
|
|
66
71
|
],
|
|
67
72
|
};
|
|
68
73
|
},
|
|
69
74
|
register(router, h) {
|
|
70
|
-
router.post('
|
|
75
|
+
router.post(accountPath('confirm'), async (ctx) => {
|
|
71
76
|
const c = await h.contextFrom(ctx);
|
|
72
77
|
// ANTES de qualquer verificação: o host desligou este método?
|
|
73
78
|
// A rota é montada incondicionalmente (decisão de tempo de registro),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { markSudo } from '../sudo_mode.js';
|
|
2
1
|
import { accountHome } from '../account_home.js';
|
|
2
|
+
import { accountPath } from '../account_paths.js';
|
|
3
|
+
import { validateReturnTo } from '../controllers/account_session_controller.js';
|
|
3
4
|
import { translate } from '../i18n.js';
|
|
4
5
|
import { ACCOUNT_SESSION_KEY } from '../middleware/account_auth.js';
|
|
5
|
-
import {
|
|
6
|
+
import { markSudo } from '../sudo_mode.js';
|
|
6
7
|
/** Último método usado com sucesso — só ordena a tela, não restringe nada. */
|
|
7
8
|
export const LAST_METHOD_SESSION_KEY = 'authkit_sudo_last_method';
|
|
8
9
|
/**
|
|
@@ -201,12 +202,7 @@ applyThrottle) {
|
|
|
201
202
|
const assertWrappableHandler = (verb, pattern, handler) => {
|
|
202
203
|
if (typeof handler === 'function')
|
|
203
204
|
return handler;
|
|
204
|
-
throw new Error(`authkit: o método de sudo "${methodId}" registrou "${verb} ${pattern}" com um handler
|
|
205
|
-
`que não é função (${handler === undefined ? 'undefined' : typeof handler}). ` +
|
|
206
|
-
'Métodos de sudo precisam registrar handler-função para receber a barreira de ' +
|
|
207
|
-
'`config.sudo.methods` — uma tupla `[Controller, \'metodo\']` registraria uma rota que ' +
|
|
208
|
-
'a config não desabilita e que alcança `completeSudo`. Envolva o controller numa ' +
|
|
209
|
-
"função: `router.post(pattern, (ctx) => new Controller().metodo(ctx))`.");
|
|
205
|
+
throw new Error(`authkit: o método de sudo "${methodId}" registrou "${verb} ${pattern}" com um handler que não é função (${handler === undefined ? 'undefined' : typeof handler}). Métodos de sudo precisam registrar handler-função para receber a barreira de \`config.sudo.methods\` — uma tupla \`[Controller, 'metodo']\` registraria uma rota que a config não desabilita e que alcança \`completeSudo\`. Envolva o controller numa função: \`router.post(pattern, (ctx) => new Controller().metodo(ctx))\`.`);
|
|
210
206
|
};
|
|
211
207
|
const wrapIfFn = (verb, pattern, handler) => wrap(assertWrappableHandler(verb, pattern, handler));
|
|
212
208
|
return new Proxy(router, {
|
|
@@ -238,10 +234,7 @@ applyThrottle) {
|
|
|
238
234
|
// desabilita.
|
|
239
235
|
if (ROUTER_CONTROLLER_SHORTCUTS.includes(prop)) {
|
|
240
236
|
return (pattern) => {
|
|
241
|
-
throw new Error(`authkit: o método de sudo "${methodId}" chamou router.${String(prop)}("${pattern}"),
|
|
242
|
-
'que registra rotas a partir de um controller e portanto não pode receber a ' +
|
|
243
|
-
'barreira de `config.sudo.methods`. Registre as rotas do método uma a uma, com ' +
|
|
244
|
-
'handler-função.');
|
|
237
|
+
throw new Error(`authkit: o método de sudo "${methodId}" chamou router.${String(prop)}("${pattern}"), que registra rotas a partir de um controller e portanto não pode receber a barreira de \`config.sudo.methods\`. Registre as rotas do método uma a uma, com handler-função.`);
|
|
245
238
|
};
|
|
246
239
|
}
|
|
247
240
|
// Todo o RESTO da API do `Router` (`group`, `on`, `where`, `use`, ...)
|
|
@@ -295,7 +288,7 @@ export async function completeSudo(c, methodId) {
|
|
|
295
288
|
export async function fail(c, messageKey) {
|
|
296
289
|
c.ctx.session.flash('confirmError', translate(c.cfg.messages, messageKey));
|
|
297
290
|
const qs = c.returnTo ? `?return_to=${encodeURIComponent(c.returnTo)}` : '';
|
|
298
|
-
return c.ctx.response.redirect(
|
|
291
|
+
return c.ctx.response.redirect(`${accountPath('confirm')}${qs}`);
|
|
299
292
|
}
|
|
300
293
|
/**
|
|
301
294
|
* Filtra os métodos disponíveis para esta conta e promove o último usado.
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* (a conta que confirmou). As duas juntas são a marca — ver
|
|
14
14
|
* `SUDO_ACCOUNT_SESSION_KEY`.
|
|
15
15
|
*/
|
|
16
|
+
import { accountPath } from './account_paths.js';
|
|
16
17
|
import { ACCOUNT_SESSION_KEY } from './middleware/account_auth.js';
|
|
17
18
|
import { SETTING_KEYS } from './runtime_toggles.js';
|
|
18
19
|
export const SUDO_MODE_DEFAULTS = {
|
|
@@ -218,8 +219,8 @@ export async function requireSudo(ctx, settings) {
|
|
|
218
219
|
const rawUrl = ctx.request.url?.() ?? '';
|
|
219
220
|
const qs = ctx.request.parsedUrl?.search ?? '';
|
|
220
221
|
const dest = qs ? `${rawUrl}${qs}` : rawUrl;
|
|
221
|
-
const returnTo = dest && dest !== '/' && !dest.startsWith('
|
|
222
|
+
const returnTo = dest && dest !== '/' && !dest.startsWith(accountPath('confirm'))
|
|
222
223
|
? `?return_to=${encodeURIComponent(dest)}`
|
|
223
224
|
: '';
|
|
224
|
-
return ctx.response.redirect(
|
|
225
|
+
return ctx.response.redirect(`${accountPath('confirm')}${returnTo}`);
|
|
225
226
|
}
|