@adonis-agora/authkit-server 0.47.0 → 0.49.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 +22 -7
- package/build/index.js +18 -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/account_screen_props.d.ts +163 -0
- package/build/src/host/account_screen_props.js +23 -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 +5 -8
- package/build/src/host/controllers/account_mfa_controller.js +72 -18
- 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 +116 -116
- package/build/src/host/controllers/account_session_controller.js +13 -8
- 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 +23 -58
- package/build/src/host/renderers/inertia_renderer.js +23 -58
- 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 +2 -2
- 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
|
@@ -2,18 +2,18 @@ import { existsSync } from 'node:fs';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { configProvider } from '@adonisjs/core';
|
|
4
4
|
import { RuntimeException } from '@adonisjs/core/exceptions';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { makeSingleFlightLock } from '../src/provider/single_flight_lock.js';
|
|
5
|
+
import { setBootedApp } from '../services/booted_app.js';
|
|
6
|
+
import { defaultEncryptForStore } from '../src/define_config.js';
|
|
7
|
+
import { resolveAppKey } from '../src/host/app_key.js';
|
|
9
8
|
import { resolveEffectiveKeyRotation } from '../src/host/key_rotation.js';
|
|
10
9
|
import { RuntimeSettings } from '../src/host/runtime_settings.js';
|
|
11
|
-
import { defaultEncryptForStore } from '../src/define_config.js';
|
|
12
|
-
import { resolveKeystoreVault, KeystoreManager } from '../src/keys/keystore_manager.js';
|
|
13
10
|
import { KeystoreCodec } from '../src/keys/keystore_codec.js';
|
|
14
11
|
import { loadEncryptionService } from '../src/keys/keystore_crypto.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
12
|
+
import { KeystoreManager, resolveKeystoreVault } from '../src/keys/keystore_manager.js';
|
|
13
|
+
import { KeyRotationScheduler } from '../src/provider/key_rotation_scheduler.js';
|
|
14
|
+
import { KeystoreReloadPoller } from '../src/provider/keystore_reload.js';
|
|
15
|
+
import { OidcService } from '../src/provider/oidc_service.js';
|
|
16
|
+
import { makeSingleFlightLock } from '../src/provider/single_flight_lock.js';
|
|
17
17
|
export default class AuthkitServerProvider {
|
|
18
18
|
app;
|
|
19
19
|
constructor(app) {
|
|
@@ -112,7 +112,10 @@ export default class AuthkitServerProvider {
|
|
|
112
112
|
if (jwksInput?.source === 'managed' && jwksInput?.store) {
|
|
113
113
|
const appRef = this.app;
|
|
114
114
|
const buildManager = async () => {
|
|
115
|
-
const vault = resolveKeystoreVault(jwksInput.store, {
|
|
115
|
+
const vault = resolveKeystoreVault(jwksInput.store, {
|
|
116
|
+
makePath: (p) => appRef.makePath(p),
|
|
117
|
+
container: appRef.container,
|
|
118
|
+
});
|
|
116
119
|
const encrypt = jwksInput.encrypt ?? defaultEncryptForStore(jwksInput.store);
|
|
117
120
|
// best-effort (≠ boot, que lança): se a encryption sumir em runtime, o reload
|
|
118
121
|
// degrada para "sem hot-reload" (o onError do poller engole) em vez de derrubar o processo.
|
|
@@ -130,7 +133,11 @@ export default class AuthkitServerProvider {
|
|
|
130
133
|
};
|
|
131
134
|
keystoreManager = async () => buildManager();
|
|
132
135
|
}
|
|
133
|
-
return new OidcService(config, appKey, metrics, {
|
|
136
|
+
return new OidcService(config, appKey, metrics, {
|
|
137
|
+
jwksLoader,
|
|
138
|
+
keystoreHead,
|
|
139
|
+
keystoreManager,
|
|
140
|
+
});
|
|
134
141
|
});
|
|
135
142
|
this.app.container.singleton('authkit.metrics', async () => {
|
|
136
143
|
const value = this.app.config.get('authkit');
|
|
@@ -238,7 +245,9 @@ export default class AuthkitServerProvider {
|
|
|
238
245
|
// conexão que o resto do authkit (mesmo padrão do expire_scan_command).
|
|
239
246
|
const value = this.app.config.get('authkit');
|
|
240
247
|
const config = value
|
|
241
|
-
? (await configProvider
|
|
248
|
+
? (await configProvider
|
|
249
|
+
.resolve(this.app, value)
|
|
250
|
+
.catch(() => null))
|
|
242
251
|
: null;
|
|
243
252
|
const connection = config?.schema?.connection;
|
|
244
253
|
// RuntimeSettings sem request (mesmo padrão de expire_scan_command / security_notice_service).
|
package/build/services/main.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OidcService } from
|
|
1
|
+
import type { OidcService } from '../src/provider/oidc_service.js';
|
|
2
2
|
/**
|
|
3
3
|
* Acessor singleton do {@link OidcService}, seguindo a convenção `services/main` do
|
|
4
4
|
* AdonisJS (igual `@adonisjs/lucid/services/db`, `@adonisjs/drive/services/main` e
|
package/build/services/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getBootedApp } from
|
|
1
|
+
import { getBootedApp } from './booted_app.js';
|
|
2
2
|
/**
|
|
3
3
|
* Acessor singleton do {@link OidcService}, seguindo a convenção `services/main` do
|
|
4
4
|
* AdonisJS (igual `@adonisjs/lucid/services/db`, `@adonisjs/drive/services/main` e
|
|
@@ -23,6 +23,6 @@ import { getBootedApp } from "./booted_app.js";
|
|
|
23
23
|
let service;
|
|
24
24
|
const app = getBootedApp();
|
|
25
25
|
await app.booted(async () => {
|
|
26
|
-
service = await app.container.make(
|
|
26
|
+
service = await app.container.make('authkit.server');
|
|
27
27
|
});
|
|
28
28
|
export { service as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import type { AuditSink } from '../audit/audit_sink.js';
|
|
2
|
+
import { type PasswordConfigInput } from '../password/password_manager.js';
|
|
3
|
+
import type { FetchLike, PwnedLogger } from '../password/pwned.js';
|
|
1
4
|
import type { AccountStore } from './account_store.js';
|
|
2
5
|
import { type AccountSecretEncrypter, type WebauthnCeremonies } from './lucid_store/shared.js';
|
|
3
|
-
import { type PasswordConfigInput } from '../password/password_manager.js';
|
|
4
|
-
import type { AuditSink } from '../audit/audit_sink.js';
|
|
5
|
-
import type { PwnedLogger, FetchLike } from '../password/pwned.js';
|
|
6
6
|
export type { AccountSecretEncrypter, WebauthnCeremonies };
|
|
7
7
|
/**
|
|
8
8
|
* Serviço de encryption do app (APP_KEY), carregado LAZY via import dinâmico.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse, verifyRegistrationResponse, } from '@simplewebauthn/server';
|
|
2
|
-
import {
|
|
2
|
+
import { PasswordManager } from '../password/password_manager.js';
|
|
3
3
|
import { buildCore } from './lucid_store/core.js';
|
|
4
4
|
import { buildMfa } from './lucid_store/mfa.js';
|
|
5
|
+
import { buildOrganizations } from './lucid_store/organizations.js';
|
|
6
|
+
import { buildPasswordExpiration, buildPasswordHistory } from './lucid_store/password_hygiene.js';
|
|
5
7
|
import { buildProviderIdentity } from './lucid_store/provider_identity.js';
|
|
8
|
+
import { hasTable, } from './lucid_store/shared.js';
|
|
9
|
+
import { buildDeletion, buildEmailVerificationStatus, buildProfile, buildStatus, hasColumn, } from './lucid_store/status_profile.js';
|
|
6
10
|
import { buildWebauthn } from './lucid_store/webauthn.js';
|
|
7
|
-
import { buildStatus, buildProfile, buildEmailVerificationStatus, buildDeletion, hasColumn, } from './lucid_store/status_profile.js';
|
|
8
|
-
import { buildOrganizations } from './lucid_store/organizations.js';
|
|
9
|
-
import { buildPasswordHistory, buildPasswordExpiration } from './lucid_store/password_hygiene.js';
|
|
10
|
-
import { PasswordManager } from '../password/password_manager.js';
|
|
11
11
|
let encSvc;
|
|
12
12
|
let encLoading;
|
|
13
13
|
/** Resolve quando o `loadEncryption()` corrente terminar (sucesso OU falha). */
|
|
@@ -192,9 +192,7 @@ export function lucidAccountStore(Model, options = {}) {
|
|
|
192
192
|
// Status (disable/enable) só quando o model tem a coluna `disabled_at`.
|
|
193
193
|
...(hasColumn(Model, 'disabledAt') ? buildStatus(ctx) : {}),
|
|
194
194
|
// Perfil (nome/avatar) só quando o model tem ao menos uma das colunas.
|
|
195
|
-
...(hasColumn(Model, 'fullName') || hasColumn(Model, 'avatarUrl')
|
|
196
|
-
? buildProfile(ctx)
|
|
197
|
-
: {}),
|
|
195
|
+
...(hasColumn(Model, 'fullName') || hasColumn(Model, 'avatarUrl') ? buildProfile(ctx) : {}),
|
|
198
196
|
// Estado de verificação de e-mail (leitura) só quando o model tem a coluna.
|
|
199
197
|
...(hasColumn(Model, 'emailVerifiedAt') ? buildEmailVerificationStatus(ctx) : {}),
|
|
200
198
|
// Deleção da conta: sempre disponível (qualquer model Lucid pode deletar).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { DateTime } from 'luxon';
|
|
3
2
|
import { Scrypt } from '@adonisjs/core/hash/drivers/scrypt';
|
|
3
|
+
import { DateTime } from 'luxon';
|
|
4
4
|
import { hasColumn } from './status_profile.js';
|
|
5
5
|
/** Prefixo do token de troca de e-mail (reaproveita a coluna emailVerificationToken). */
|
|
6
6
|
const EMAIL_CHANGE_PREFIX = 'ec:';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { authenticator } from 'otplib';
|
|
2
|
-
import { generateRecoveryCode, hashesEqual, sha256,
|
|
2
|
+
import { buildMfaStateRepo, generateRecoveryCode, hashesEqual, sha256, } from './shared.js';
|
|
3
3
|
/**
|
|
4
4
|
* Capacidade de MFA / TOTP — LIB-OWNED.
|
|
5
5
|
*
|
|
@@ -201,9 +201,7 @@ export function buildOrganizations(ctx) {
|
|
|
201
201
|
return rows.map(toOrgInvitation);
|
|
202
202
|
},
|
|
203
203
|
async listPendingInvitationsForEmail(email) {
|
|
204
|
-
const rows = await InvitationModel.query()
|
|
205
|
-
.where('email', email)
|
|
206
|
-
.whereNull('accepted_at');
|
|
204
|
+
const rows = await InvitationModel.query().where('email', email).whereNull('accepted_at');
|
|
207
205
|
return rows.map(toOrgInvitation);
|
|
208
206
|
},
|
|
209
207
|
async acceptInvitation(invitationId, accountId) {
|
|
@@ -227,7 +225,7 @@ export function buildOrganizations(ctx) {
|
|
|
227
225
|
else {
|
|
228
226
|
expiresMs = 0;
|
|
229
227
|
}
|
|
230
|
-
if (isNaN(expiresMs) || expiresMs < Date.now())
|
|
228
|
+
if (Number.isNaN(expiresMs) || expiresMs < Date.now())
|
|
231
229
|
return { ok: false, reason: 'expired' };
|
|
232
230
|
// Verifica e-mail
|
|
233
231
|
const accountEmail = await findAccountEmail(accountId);
|
|
@@ -74,10 +74,7 @@ export function buildPasswordHistory(ctx, db) {
|
|
|
74
74
|
return; // menos registros que o limite → nada a podar
|
|
75
75
|
// Apaga os mais antigos (todos exceto os últimos `count`).
|
|
76
76
|
const keepIds = rows.map((r) => r.id);
|
|
77
|
-
await qFrom()
|
|
78
|
-
.where('account_id', accountId)
|
|
79
|
-
.whereNotIn('id', keepIds)
|
|
80
|
-
.delete();
|
|
77
|
+
await qFrom().where('account_id', accountId).whereNotIn('id', keepIds).delete();
|
|
81
78
|
}
|
|
82
79
|
catch {
|
|
83
80
|
// Best-effort.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse, verifyRegistrationResponse } from '@simplewebauthn/server';
|
|
2
|
-
import type { AuthAccount } from '../account_store.js';
|
|
3
2
|
import type { AuditSink } from '../../audit/audit_sink.js';
|
|
4
3
|
import type { PasswordManager } from '../../password/password_manager.js';
|
|
4
|
+
import type { AuthAccount } from '../account_store.js';
|
|
5
5
|
/**
|
|
6
6
|
* Encripta/decripta um valor (ex.: o segredo TOTP) em repouso. Mantém a lib
|
|
7
7
|
* desacoplada do serviço de encryption do app — qualquer implementação que
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type LucidAccountStoreOptions } from './lucid_account_store.js';
|
|
2
|
-
import type { AccountStore } from './account_store.js';
|
|
3
|
-
import type { PatStore } from '../pat/pat_store.js';
|
|
4
1
|
import type { AuditSink } from '../audit/audit_sink.js';
|
|
2
|
+
import type { PatStore } from '../pat/pat_store.js';
|
|
3
|
+
import type { AccountStore } from './account_store.js';
|
|
4
|
+
import { type LucidAccountStoreOptions } from './lucid_account_store.js';
|
|
5
5
|
/** Models Lucid (compostos dos mixins do authkit) para montar os stores de uma vez. */
|
|
6
6
|
export interface LucidStoresModels {
|
|
7
7
|
/** Model de `withAuthUser()` (+withCredentials/+withMfa). Obrigatório. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { lucidAccountStore } from './lucid_account_store.js';
|
|
2
|
-
import { lucidPatStore } from '../pat/lucid_pat_store.js';
|
|
3
1
|
import { lucidAuditSink } from '../audit/lucid_audit_sink.js';
|
|
2
|
+
import { lucidPatStore } from '../pat/lucid_pat_store.js';
|
|
3
|
+
import { lucidAccountStore } from './lucid_account_store.js';
|
|
4
4
|
/**
|
|
5
5
|
* Conveniência que monta `accountStore` (+ `patStore` + `audit`) a partir dos models,
|
|
6
6
|
* declarando `mfaIssuer`/`webauthn`/`encrypter` UMA vez. Substitui o wiring repetido
|
|
@@ -52,7 +52,9 @@ export class DatabaseAdapter {
|
|
|
52
52
|
if (!found)
|
|
53
53
|
return;
|
|
54
54
|
found.consumed = Math.floor(Date.now() / 1000);
|
|
55
|
-
await this.#query()
|
|
55
|
+
await this.#query()
|
|
56
|
+
.where('id', id)
|
|
57
|
+
.update({ payload: JSON.stringify(found) });
|
|
56
58
|
}
|
|
57
59
|
async destroy(id) {
|
|
58
60
|
await this.#query().where('id', id).delete();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { RedisAdapter } from './redis_adapter.js';
|
|
2
1
|
import { DatabaseAdapter } from './database_adapter.js';
|
|
2
|
+
import { RedisAdapter } from './redis_adapter.js';
|
|
3
3
|
export const adapters = {
|
|
4
4
|
/**
|
|
5
5
|
* Factory para o adapter Redis. O consumidor precisa ter o @adonisjs/redis
|
|
@@ -88,7 +88,8 @@ export class RedisAdapter {
|
|
|
88
88
|
const gk = this.#grantKey(grantId);
|
|
89
89
|
const keys = await this.redis.lrange(gk, 0, -1);
|
|
90
90
|
const multi = this.redis.multi();
|
|
91
|
-
|
|
91
|
+
for (const k of keys)
|
|
92
|
+
multi.del(k);
|
|
92
93
|
multi.del(gk);
|
|
93
94
|
await multi.exec();
|
|
94
95
|
}
|
|
@@ -27,9 +27,9 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
27
27
|
}
|
|
28
28
|
return path;
|
|
29
29
|
};
|
|
30
|
-
import { resolveAuthkitConfig } from './resolve_config.js';
|
|
31
30
|
import { RuntimeSettings } from '../host/runtime_settings.js';
|
|
32
31
|
import { resolveEffectiveAccountExpiration } from '../host/runtime_toggles.js';
|
|
32
|
+
import { resolveAuthkitConfig } from './resolve_config.js';
|
|
33
33
|
// ---------------------------------------------------------------------------
|
|
34
34
|
// Core logic (pura, testável sem Ace)
|
|
35
35
|
// ---------------------------------------------------------------------------
|
|
@@ -101,7 +101,11 @@ export async function runExpireScan(app, opts) {
|
|
|
101
101
|
else if (warnDays > 0 && lastMs < warnCutoffMs) {
|
|
102
102
|
// A expirar em breve.
|
|
103
103
|
const daysUntilExpiry = Math.ceil((lastMs + inactiveDays * 24 * 60 * 60 * 1000 - nowMs) / (24 * 60 * 60 * 1000));
|
|
104
|
-
warnSoon.push({
|
|
104
|
+
warnSoon.push({
|
|
105
|
+
accountId: account.id,
|
|
106
|
+
email: account.email,
|
|
107
|
+
expiresInDays: daysUntilExpiry,
|
|
108
|
+
});
|
|
105
109
|
if (warn && !dryRun) {
|
|
106
110
|
// Verifica se já foi avisado dentro da janela de warnDays dias.
|
|
107
111
|
const alreadyWarned = await wasWarnedRecently(audit, account.id, warnDays);
|
|
@@ -150,7 +154,12 @@ export async function runExpireScan(app, opts) {
|
|
|
150
154
|
/** Retorna o timestamp em ms do último login.success da conta, ou null se nunca logou. */
|
|
151
155
|
async function getLastLoginMs(audit, accountId) {
|
|
152
156
|
try {
|
|
153
|
-
const result = await audit.list({
|
|
157
|
+
const result = await audit.list({
|
|
158
|
+
type: 'login.success',
|
|
159
|
+
subject: accountId,
|
|
160
|
+
page: 1,
|
|
161
|
+
limit: 1,
|
|
162
|
+
});
|
|
154
163
|
if (result.data.length === 0)
|
|
155
164
|
return null;
|
|
156
165
|
const createdAt = result.data[0].createdAt;
|
|
@@ -169,7 +178,12 @@ async function getLastLoginMs(audit, accountId) {
|
|
|
169
178
|
*/
|
|
170
179
|
async function wasWarnedRecently(audit, accountId, warnDays) {
|
|
171
180
|
try {
|
|
172
|
-
const result = await audit.list({
|
|
181
|
+
const result = await audit.list({
|
|
182
|
+
type: 'account.expiration_warned',
|
|
183
|
+
subject: accountId,
|
|
184
|
+
page: 1,
|
|
185
|
+
limit: 1,
|
|
186
|
+
});
|
|
173
187
|
if (result.data.length === 0)
|
|
174
188
|
return false;
|
|
175
189
|
const lastWarned = result.data[0].createdAt;
|
|
@@ -201,7 +215,7 @@ async function sendWarnEmail(cfg, account, expiresInDays) {
|
|
|
201
215
|
await mail.send((message) => {
|
|
202
216
|
message
|
|
203
217
|
.to(account.email)
|
|
204
|
-
.subject(
|
|
218
|
+
.subject('Your account will be deactivated due to inactivity')
|
|
205
219
|
.html(`<p>Your account will be deactivated in <strong>${expiresInDays} day(s)</strong> due to inactivity. Sign in to keep your account active.</p>`)
|
|
206
220
|
.text(`Your account will be deactivated in ${expiresInDays} day(s) due to inactivity. Sign in to keep your account active.`);
|
|
207
221
|
});
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
* Todas suportam --json para output machine-readable.
|
|
16
16
|
*/
|
|
17
17
|
import { RuntimeSettings } from '../host/runtime_settings.js';
|
|
18
|
-
import { resolveAuthkitConfig } from './resolve_config.js';
|
|
19
18
|
import { SETTING_KEYS } from '../host/runtime_toggles.js';
|
|
19
|
+
import { resolveAuthkitConfig } from './resolve_config.js';
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
21
|
// Known-key shape validators (best-effort — warn only, não rejeita)
|
|
22
22
|
// ---------------------------------------------------------------------------
|
|
@@ -31,7 +31,13 @@ function validateKnownKey(key, value) {
|
|
|
31
31
|
const obj = value;
|
|
32
32
|
switch (key) {
|
|
33
33
|
case SETTING_KEYS.LOCKOUT: {
|
|
34
|
-
const fields = [
|
|
34
|
+
const fields = [
|
|
35
|
+
'enabled',
|
|
36
|
+
'maxAttempts',
|
|
37
|
+
'windowSec',
|
|
38
|
+
'baseLockoutSec',
|
|
39
|
+
'maxLockoutSec',
|
|
40
|
+
];
|
|
35
41
|
for (const f of fields) {
|
|
36
42
|
if (f in obj && f === 'enabled' && typeof obj[f] !== 'boolean')
|
|
37
43
|
return `lockout.${f} must be boolean`;
|
|
@@ -55,13 +61,19 @@ function validateKnownKey(key, value) {
|
|
|
55
61
|
return null;
|
|
56
62
|
}
|
|
57
63
|
case SETTING_KEYS.PASSWORD_POLICY: {
|
|
58
|
-
const boolFields = [
|
|
64
|
+
const boolFields = [
|
|
65
|
+
'requireUppercase',
|
|
66
|
+
'requireLowercase',
|
|
67
|
+
'requireNumbers',
|
|
68
|
+
'requireSymbols',
|
|
69
|
+
'checkPwned',
|
|
70
|
+
];
|
|
59
71
|
for (const f of boolFields) {
|
|
60
72
|
if (f in obj && typeof obj[f] !== 'boolean')
|
|
61
73
|
return `password_policy.${f} must be boolean`;
|
|
62
74
|
}
|
|
63
75
|
if ('minLength' in obj && typeof obj.minLength !== 'number')
|
|
64
|
-
return
|
|
76
|
+
return 'password_policy.minLength must be number';
|
|
65
77
|
return null;
|
|
66
78
|
}
|
|
67
79
|
case SETTING_KEYS.NOTIFICATIONS: {
|
|
@@ -145,7 +157,12 @@ export async function settingsList(app, opts) {
|
|
|
145
157
|
}
|
|
146
158
|
const rows = await svc.listSettings();
|
|
147
159
|
if (opts.json) {
|
|
148
|
-
opts.logger.info(JSON.stringify(rows.map((r) => ({
|
|
160
|
+
opts.logger.info(JSON.stringify(rows.map((r) => ({
|
|
161
|
+
key: r.key,
|
|
162
|
+
value: r.value,
|
|
163
|
+
updatedAt: r.updatedAt,
|
|
164
|
+
updatedBy: r.updatedBy,
|
|
165
|
+
}))));
|
|
149
166
|
return;
|
|
150
167
|
}
|
|
151
168
|
if (rows.length === 0) {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
4
|
-
import type
|
|
5
|
-
import type {
|
|
6
|
-
import type
|
|
7
|
-
import type
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
10
|
-
import { type AuthMessages, type I18nConfig } from
|
|
11
|
-
import
|
|
12
|
-
import { type
|
|
13
|
-
import type {
|
|
1
|
+
import type { AccessTokenFormat, AccessTokensConfig, ClientConfig, JwksConfig, KeystoreStoreConfig, ObservabilityConfig, TtlConfig } from '@adonis-agora/authkit-core';
|
|
2
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
3
|
+
import type { AccountStore, AuthAccount } from './accounts/account_store.js';
|
|
4
|
+
import { type AdapterFactory, type OidcAdapterClass, adapters } from './adapters/factory.js';
|
|
5
|
+
import type { AuditSink } from './audit/audit_sink.js';
|
|
6
|
+
import { type EventsConfigInput } from './events/dispatcher.js';
|
|
7
|
+
import { type BotProtectionConfigInput, type ResolvedBotProtectionConfig } from './host/bot_protection.js';
|
|
8
|
+
import type { BrandingConfig } from './host/branding.js';
|
|
9
|
+
import type { ResolveGeo } from './host/geo.js';
|
|
10
|
+
import { type AuthMessages, type I18nConfig } from './host/i18n.js';
|
|
11
|
+
import type { SudoMethod } from './host/sudo/types.js';
|
|
12
|
+
import { type ResolvedTrustedDevicesConfig, type TrustedDevicesConfigInput } from './host/trusted_device.js';
|
|
13
|
+
import type { PatStore } from './pat/pat_store.js';
|
|
14
14
|
export { adapters };
|
|
15
15
|
export type { AuthAccount };
|
|
16
16
|
export type AuthHostRenderer = (ctx: HttpContext, view: string, props: Record<string, unknown>) => unknown;
|
|
@@ -120,7 +120,7 @@ export interface MailHooks {
|
|
|
120
120
|
id: string;
|
|
121
121
|
email: string;
|
|
122
122
|
};
|
|
123
|
-
kind:
|
|
123
|
+
kind: 'password_changed' | 'mfa_enabled' | 'mfa_disabled' | 'passkey_added' | 'passkey_removed' | 'email_changed';
|
|
124
124
|
ip?: string | null;
|
|
125
125
|
userAgent?: string | null;
|
|
126
126
|
timestamp: string;
|
|
@@ -282,7 +282,7 @@ export interface UploadsConfigInput {
|
|
|
282
282
|
* `'builtin'` força o `@adonisjs/drive`; `'media'` força o media (degrada para
|
|
283
283
|
* o input de URL se indisponível).
|
|
284
284
|
*/
|
|
285
|
-
storage?:
|
|
285
|
+
storage?: 'auto' | 'builtin' | 'media';
|
|
286
286
|
/** Disk do `@adonisjs/drive` a usar (backend builtin). Default: o disk DEFAULT do app. */
|
|
287
287
|
disk?: string;
|
|
288
288
|
/** Diretório/prefixo das chaves (backend builtin). Default: 'authkit/avatars'. */
|
|
@@ -298,7 +298,7 @@ export interface UploadsConfigInput {
|
|
|
298
298
|
export interface ResolvedUploadsConfig {
|
|
299
299
|
avatars: {
|
|
300
300
|
/** Backend ativo (default 'auto'). */
|
|
301
|
-
storage:
|
|
301
|
+
storage: 'auto' | 'builtin' | 'media';
|
|
302
302
|
/** Disk explícito; `undefined` = disk DEFAULT do app (backend builtin). */
|
|
303
303
|
disk?: string;
|
|
304
304
|
directory: string;
|
|
@@ -524,7 +524,7 @@ export interface AdminApiConfigInput {
|
|
|
524
524
|
* `AUTHKIT_ADMIN_API_KEY` (uma ou várias, separadas por vírgula). Elimina o
|
|
525
525
|
* spread condicional `...(env.get('AUTHKIT_ADMIN_API_KEY') ? {...} : {})`.
|
|
526
526
|
*/
|
|
527
|
-
apiKeys?: string[] |
|
|
527
|
+
apiKeys?: string[] | 'env';
|
|
528
528
|
}
|
|
529
529
|
export interface ResolvedAdminApiConfig {
|
|
530
530
|
enabled: boolean;
|
|
@@ -550,7 +550,7 @@ export interface OrganizationsConfigInput {
|
|
|
550
550
|
* emite org_id/org_slug/org_role da org ativa da sessão via cookie assinado.
|
|
551
551
|
* Default: 'active'.
|
|
552
552
|
*/
|
|
553
|
-
claimStrategy?:
|
|
553
|
+
claimStrategy?: 'active';
|
|
554
554
|
}
|
|
555
555
|
export interface ResolvedOrganizationsConfig {
|
|
556
556
|
/** `undefined` = auto (decide em runtime pelo capability-probing do store). */
|
|
@@ -558,7 +558,7 @@ export interface ResolvedOrganizationsConfig {
|
|
|
558
558
|
roles: string[];
|
|
559
559
|
allowSelfCreate: boolean;
|
|
560
560
|
invitationTtlHours: number;
|
|
561
|
-
claimStrategy:
|
|
561
|
+
claimStrategy: 'active';
|
|
562
562
|
}
|
|
563
563
|
export declare function resolveOrganizations(input?: OrganizationsConfigInput): ResolvedOrganizationsConfig;
|
|
564
564
|
/**
|
|
@@ -601,7 +601,7 @@ export interface AuthServerConfigInput {
|
|
|
601
601
|
* persistido em arquivo (`tmp/authkit_jwks.json`) p/ dev. Elimina o ternário
|
|
602
602
|
* env-aware que todo app escrevia.
|
|
603
603
|
*/
|
|
604
|
-
jwks: JwksConfig |
|
|
604
|
+
jwks: JwksConfig | 'auto';
|
|
605
605
|
ttl?: TtlConfig;
|
|
606
606
|
/** Nome da CLAIM (não do scope) onde os papéis globais são emitidos. Default: 'roles'. */
|
|
607
607
|
globalRolesClaim?: string;
|