@adonis-agora/authkit-server 0.45.0 → 0.47.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/ui_preset.js +15 -1
- package/build/host/views/account/confirm.edge +118 -52
- package/build/host/views/account/mfa.edge +1 -1
- package/build/host/views/login.edge +2 -4
- package/build/host/views/mfa-challenge.edge +1 -1
- package/build/host/views/otp-unlock.edge +2 -2
- package/build/host/views/partials/styles.edge +1 -1
- package/build/index.d.ts +5 -1
- package/build/index.js +15 -1
- package/build/providers/authkit_server_provider.js +7 -0
- package/build/services/booted_app.d.ts +8 -0
- package/build/services/booted_app.js +27 -0
- package/build/services/main.d.ts +7 -0
- package/build/services/main.js +9 -1
- package/build/src/define_config.d.ts +51 -0
- package/build/src/define_config.js +8 -0
- package/build/src/host/account_login_url.d.ts +41 -0
- package/build/src/host/account_login_url.js +50 -0
- package/build/src/host/admin_sessions_service.d.ts +3 -1
- package/build/src/host/admin_sessions_service.js +35 -3
- package/build/src/host/assets/webauthn.js +2 -0
- package/build/src/host/console_session.d.ts +4 -0
- package/build/src/host/console_session.js +9 -2
- package/build/src/host/controllers/account_confirm_controller.d.ts +11 -14
- package/build/src/host/controllers/account_confirm_controller.js +42 -130
- package/build/src/host/controllers/account_orgs_controller.js +7 -4
- package/build/src/host/controllers/account_security_controller.js +3 -2
- package/build/src/host/controllers/account_session_controller.js +23 -5
- package/build/src/host/controllers/account_tokens_controller.js +11 -0
- package/build/src/host/controllers/pat_introspection_controller.js +10 -0
- package/build/src/host/controllers/webauthn_asset_controller.d.ts +22 -0
- package/build/src/host/controllers/webauthn_asset_controller.js +66 -0
- package/build/src/host/i18n.d.ts +14 -0
- package/build/src/host/i18n.js +16 -0
- package/build/src/host/impersonation_session.js +15 -0
- package/build/src/host/middleware/account_auth.js +3 -1
- package/build/src/host/rate_limit.d.ts +10 -0
- package/build/src/host/rate_limit.js +6 -0
- package/build/src/host/register_auth_host.d.ts +85 -2
- package/build/src/host/register_auth_host.js +188 -61
- package/build/src/host/renderers/edge_renderer.js +6 -1
- package/build/src/host/renderers/inertia_renderer.d.ts +55 -0
- package/build/src/host/renderers/inertia_renderer.js +55 -0
- package/build/src/host/sudo/index.d.ts +47 -0
- package/build/src/host/sudo/index.js +41 -0
- package/build/src/host/sudo/methods/magic_link.d.ts +43 -0
- package/build/src/host/sudo/methods/magic_link.js +174 -0
- package/build/src/host/sudo/methods/oidc_step_up.d.ts +68 -0
- package/build/src/host/sudo/methods/oidc_step_up.js +78 -0
- package/build/src/host/sudo/methods/passkey.d.ts +28 -0
- package/build/src/host/sudo/methods/passkey.js +139 -0
- package/build/src/host/sudo/methods/password.d.ts +19 -0
- package/build/src/host/sudo/methods/password.js +93 -0
- package/build/src/host/sudo/runtime.d.ts +141 -0
- package/build/src/host/sudo/runtime.js +327 -0
- package/build/src/host/sudo/types.d.ts +93 -0
- package/build/src/host/sudo/types.js +1 -0
- package/build/src/host/sudo_mode.d.ts +116 -6
- package/build/src/host/sudo_mode.js +133 -7
- package/package.json +6 -2
- package/build/stubs/ui/edge/views/consent.edge +0 -13
- package/build/stubs/ui/edge/views/login.edge +0 -19
- package/stubs/ui/edge/views/consent.edge +0 -13
- package/stubs/ui/edge/views/login.edge +0 -19
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { HttpContext } from '@adonisjs/core/http';
|
|
2
|
+
/**
|
|
3
|
+
* GET /authkit/assets/webauthn.js
|
|
4
|
+
*
|
|
5
|
+
* Serve o `@simplewebauthn/browser` a partir do próprio host, substituindo o
|
|
6
|
+
* import de `cdn.jsdelivr.net` que as views de login/MFA/confirm faziam.
|
|
7
|
+
*
|
|
8
|
+
* SEM AUTENTICAÇÃO, e é intencional: é asset estático necessário na tela de
|
|
9
|
+
* login, ou seja, antes de existir qualquer sessão. Também não pode viver sob
|
|
10
|
+
* o prefixo do console admin (que é opt-in) — `login.edge` e
|
|
11
|
+
* `mfa-challenge.edge` precisam do script mesmo num host sem console.
|
|
12
|
+
*/
|
|
13
|
+
export default class WebauthnAssetController {
|
|
14
|
+
handle(ctx: HttpContext): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Limpa o cache do bundle. Existe para os testes conseguirem exercitar tanto o
|
|
18
|
+
* caminho feliz quanto o 404 no mesmo processo.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export declare function resetWebauthnAssetCache(): void;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* URL do bundle ESM do `@simplewebauthn/browser` empacotado por
|
|
4
|
+
* `scripts/build_webauthn.mjs`.
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ RESOLVIDO VIA `import.meta.url`, NUNCA relativo ao cwd. Os apps que
|
|
7
|
+
* consomem este pacote rodam `pnpm deploy --legacy`, que remonta a árvore de
|
|
8
|
+
* `node_modules` num diretório novo — um caminho relativo ao cwd do host
|
|
9
|
+
* apontaria para o lugar errado e a rota daria 404 em produção. Ancorado no
|
|
10
|
+
* módulo, o caminho segue o pacote para onde quer que ele seja copiado.
|
|
11
|
+
*
|
|
12
|
+
* Funciona nos dois layouts porque o bundle é commitado em `src/host/assets/`
|
|
13
|
+
* e copiado para `build/src/host/assets/` pelo script `build`:
|
|
14
|
+
* dev → src/host/controllers/… → src/host/assets/webauthn.js
|
|
15
|
+
* build → build/src/host/controllers/… → build/src/host/assets/webauthn.js
|
|
16
|
+
*/
|
|
17
|
+
const BUNDLE_URL = new URL('../assets/webauthn.js', import.meta.url);
|
|
18
|
+
/**
|
|
19
|
+
* Cache do conteúdo do bundle. É imutável por versão do pacote — ler do disco
|
|
20
|
+
* a cada request de tela de login não compra nada.
|
|
21
|
+
*
|
|
22
|
+
* `null` = ainda não lido. `false` = lido e ausente (404 memoizado); sem isso
|
|
23
|
+
* um bundle faltando viraria um `readFile` que falha por request.
|
|
24
|
+
*/
|
|
25
|
+
let cached = null;
|
|
26
|
+
/**
|
|
27
|
+
* GET /authkit/assets/webauthn.js
|
|
28
|
+
*
|
|
29
|
+
* Serve o `@simplewebauthn/browser` a partir do próprio host, substituindo o
|
|
30
|
+
* import de `cdn.jsdelivr.net` que as views de login/MFA/confirm faziam.
|
|
31
|
+
*
|
|
32
|
+
* SEM AUTENTICAÇÃO, e é intencional: é asset estático necessário na tela de
|
|
33
|
+
* login, ou seja, antes de existir qualquer sessão. Também não pode viver sob
|
|
34
|
+
* o prefixo do console admin (que é opt-in) — `login.edge` e
|
|
35
|
+
* `mfa-challenge.edge` precisam do script mesmo num host sem console.
|
|
36
|
+
*/
|
|
37
|
+
export default class WebauthnAssetController {
|
|
38
|
+
async handle(ctx) {
|
|
39
|
+
if (cached === null) {
|
|
40
|
+
try {
|
|
41
|
+
cached = await readFile(BUNDLE_URL);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
cached = false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (cached === false) {
|
|
48
|
+
// 404 limpo: o bundle não foi gerado (`node scripts/build_webauthn.mjs`).
|
|
49
|
+
// A tela degrada para os demais fatores em vez de estourar 500.
|
|
50
|
+
return ctx.response.notFound();
|
|
51
|
+
}
|
|
52
|
+
return ctx.response
|
|
53
|
+
.type('text/javascript')
|
|
54
|
+
.header('Cache-Control', 'public, max-age=31536000, immutable')
|
|
55
|
+
.send(cached);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Limpa o cache do bundle. Existe para os testes conseguirem exercitar tanto o
|
|
60
|
+
* caminho feliz quanto o 404 no mesmo processo.
|
|
61
|
+
*
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
export function resetWebauthnAssetCache() {
|
|
65
|
+
cached = null;
|
|
66
|
+
}
|
package/build/src/host/i18n.d.ts
CHANGED
|
@@ -560,6 +560,13 @@ export declare const DEFAULT_MESSAGES: {
|
|
|
560
560
|
"account.confirm.error": string;
|
|
561
561
|
"account.confirm.passkey_error": string;
|
|
562
562
|
"account.confirm.passwordless_notice": string;
|
|
563
|
+
"account.confirm.method.password": string;
|
|
564
|
+
"account.confirm.method.passkey": string;
|
|
565
|
+
"account.confirm.method.magic_link": string;
|
|
566
|
+
"account.confirm.method.oidc_step_up": string;
|
|
567
|
+
"account.confirm.magic_link_sent": string;
|
|
568
|
+
"account.confirm.no_methods": string;
|
|
569
|
+
"account.confirm.preferred_badge": string;
|
|
563
570
|
"admin.settings.sudo_mode_section": string;
|
|
564
571
|
"admin.settings.sudo_mode_intro": string;
|
|
565
572
|
"admin.settings.sudo_mode_from_config": string;
|
|
@@ -1242,6 +1249,13 @@ export declare const PT_BR_MESSAGES: {
|
|
|
1242
1249
|
"account.confirm.error": string;
|
|
1243
1250
|
"account.confirm.passkey_error": string;
|
|
1244
1251
|
"account.confirm.passwordless_notice": string;
|
|
1252
|
+
"account.confirm.method.password": string;
|
|
1253
|
+
"account.confirm.method.passkey": string;
|
|
1254
|
+
"account.confirm.method.magic_link": string;
|
|
1255
|
+
"account.confirm.method.oidc_step_up": string;
|
|
1256
|
+
"account.confirm.magic_link_sent": string;
|
|
1257
|
+
"account.confirm.no_methods": string;
|
|
1258
|
+
"account.confirm.preferred_badge": string;
|
|
1245
1259
|
"admin.settings.sudo_mode_section": string;
|
|
1246
1260
|
"admin.settings.sudo_mode_intro": string;
|
|
1247
1261
|
"admin.settings.sudo_mode_from_config": string;
|
package/build/src/host/i18n.js
CHANGED
|
@@ -605,6 +605,14 @@ export const DEFAULT_MESSAGES = {
|
|
|
605
605
|
"account.confirm.error": "Incorrect password.",
|
|
606
606
|
"account.confirm.passkey_error": "Could not authenticate with the passkey. Please try again.",
|
|
607
607
|
"account.confirm.passwordless_notice": "This account does not have a password. Please add a passkey to use sudo-protected features.",
|
|
608
|
+
// Rótulos dos métodos do SPI de sudo (account/confirm.edge, um bloco por método disponível).
|
|
609
|
+
"account.confirm.method.password": "Confirm with your password",
|
|
610
|
+
"account.confirm.method.passkey": "Confirm with a passkey",
|
|
611
|
+
"account.confirm.method.magic_link": "Email me a confirmation link",
|
|
612
|
+
"account.confirm.method.oidc_step_up": "Sign in again to confirm",
|
|
613
|
+
"account.confirm.magic_link_sent": "We sent a confirmation link to your email. It expires in 5 minutes.",
|
|
614
|
+
"account.confirm.no_methods": "No confirmation method is available for this account. Contact support.",
|
|
615
|
+
"account.confirm.preferred_badge": "Used last time",
|
|
608
616
|
// Admin settings — sudo_mode card.
|
|
609
617
|
"admin.settings.sudo_mode_section": "Sudo mode (identity confirmation)",
|
|
610
618
|
"admin.settings.sudo_mode_intro": "When enabled, sensitive actions (password change, email change, account deletion, MFA/passkey management, PAT creation/revocation) require the user to confirm their password. The confirmation is valid for a configurable grace period.",
|
|
@@ -1359,6 +1367,14 @@ export const PT_BR_MESSAGES = {
|
|
|
1359
1367
|
"account.confirm.error": "Senha incorreta.",
|
|
1360
1368
|
"account.confirm.passkey_error": "Não foi possível autenticar com a passkey. Tente novamente.",
|
|
1361
1369
|
"account.confirm.passwordless_notice": "Esta conta não possui senha. Adicione uma passkey para usar funcionalidades protegidas.",
|
|
1370
|
+
// Rótulos dos métodos do SPI de sudo (account/confirm.edge, um bloco por método disponível).
|
|
1371
|
+
"account.confirm.method.password": "Confirmar com a senha",
|
|
1372
|
+
"account.confirm.method.passkey": "Confirmar com passkey",
|
|
1373
|
+
"account.confirm.method.magic_link": "Receber link de confirmação por e-mail",
|
|
1374
|
+
"account.confirm.method.oidc_step_up": "Entrar de novo para confirmar",
|
|
1375
|
+
"account.confirm.magic_link_sent": "Enviamos um link de confirmação para o seu e-mail. Ele expira em 5 minutos.",
|
|
1376
|
+
"account.confirm.no_methods": "Nenhum método de confirmação está disponível para esta conta. Fale com o suporte.",
|
|
1377
|
+
"account.confirm.preferred_badge": "Usado da última vez",
|
|
1362
1378
|
// Admin settings — sudo_mode card (pt-BR).
|
|
1363
1379
|
"admin.settings.sudo_mode_section": "Modo sudo (confirmação de identidade)",
|
|
1364
1380
|
"admin.settings.sudo_mode_intro": "Quando habilitado, ações sensíveis (troca de senha, troca de e-mail, exclusão de conta, gerência de MFA/passkey, criação/revogação de PAT) exigem que o usuário confirme sua senha. A confirmação é válida por um período de graça configurável.",
|
|
@@ -98,6 +98,14 @@ export async function startImpersonation(ctx, params) {
|
|
|
98
98
|
// Anti-fixation: rotaciona o id da sessão (mantém os dados) antes de gravar a
|
|
99
99
|
// nova identidade. Mesmo padrão do consumidor real no RP.
|
|
100
100
|
await ctx.session.regenerate();
|
|
101
|
+
// ESCALAÇÃO DE PRIVILÉGIO (fechada por vinculação): trocar a conta aqui NÃO
|
|
102
|
+
// pode carregar junto o sudo que o admin confirmou sobre a PRÓPRIA conta —
|
|
103
|
+
// senão ele entraria personificando já com a graça aberta sobre a conta
|
|
104
|
+
// alheia (exportar/excluir dados, MFA, PATs). Não limpamos a marca aqui: ela
|
|
105
|
+
// é vinculada à conta que a confirmou (`SUDO_ACCOUNT_SESSION_KEY`), então
|
|
106
|
+
// `isSudoActive` a recusa sozinho assim que `ACCOUNT_SESSION_KEY` muda. A
|
|
107
|
+
// garantia é estrutural — vale para qualquer troca de conta futura, sem
|
|
108
|
+
// depender de um `forget` lembrado em cada nova transição.
|
|
101
109
|
ctx.session.put(IMPERSONATOR_SESSION_KEY, impersonatorId);
|
|
102
110
|
ctx.session.put(ACCOUNT_SESSION_KEY, params.targetId);
|
|
103
111
|
}
|
|
@@ -122,6 +130,13 @@ export async function stopImpersonation(ctx) {
|
|
|
122
130
|
if (!impersonatorId)
|
|
123
131
|
return;
|
|
124
132
|
await ctx.session.regenerate();
|
|
133
|
+
// Simétrico ao `startImpersonation`: o sudo obtido ENQUANTO personificava
|
|
134
|
+
// ficaria valendo sobre a conta do admin ao voltar. A vinculação corta isso —
|
|
135
|
+
// aquela marca aponta para a conta personificada e morre com a volta.
|
|
136
|
+
//
|
|
137
|
+
// Nota: se o admin tinha sudo sobre a própria conta ANTES de personificar e a
|
|
138
|
+
// graça ainda não venceu, ele volta valendo. Correto e intencional: é a
|
|
139
|
+
// confirmação dele, sobre a conta dele, dentro da janela dele.
|
|
125
140
|
ctx.session.put(ACCOUNT_SESSION_KEY, impersonatorId);
|
|
126
141
|
ctx.session.forget(IMPERSONATOR_SESSION_KEY);
|
|
127
142
|
ctx.session.forget(ADMIN_ACCESS_TOKEN_SESSION_KEY);
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import '../augmentations.js';
|
|
2
|
+
import { getAccountLoginUrl } from '../account_login_url.js';
|
|
2
3
|
export const ACCOUNT_SESSION_KEY = 'account_user_id';
|
|
3
4
|
export default class AccountAuthMiddleware {
|
|
4
5
|
async handle(ctx, next) {
|
|
5
6
|
const userId = ctx.session.get(ACCOUNT_SESSION_KEY);
|
|
6
7
|
if (!userId) {
|
|
7
|
-
|
|
8
|
+
// Destino configurável (`accountLoginUrl`): default `/account/login`.
|
|
9
|
+
return ctx.response.redirect(getAccountLoginUrl());
|
|
8
10
|
}
|
|
9
11
|
return next();
|
|
10
12
|
}
|
|
@@ -20,6 +20,16 @@ export interface AuthThrottles {
|
|
|
20
20
|
* de tentativas vindas do MESMO IP independentemente de qual key foi usada (M8).
|
|
21
21
|
*/
|
|
22
22
|
adminIp: ThrottleMiddleware;
|
|
23
|
+
/**
|
|
24
|
+
* Throttle das rotas dos métodos de sudo (`/account/confirm/*`), keyed por IP
|
|
25
|
+
* como o `login` — e com os MESMOS limites — mas em bucket PRÓPRIO.
|
|
26
|
+
*
|
|
27
|
+
* A separação é o ponto: `login` mede um anônimo tentando adivinhar
|
|
28
|
+
* credenciais, `sudo` mede um usuário já autenticado reprovando a própria
|
|
29
|
+
* identidade. Ver `ResolvedRateLimitConfig.sudo` para o porquê de os dois
|
|
30
|
+
* orçamentos não poderem se consumir.
|
|
31
|
+
*/
|
|
32
|
+
sudo: ThrottleMiddleware;
|
|
23
33
|
}
|
|
24
34
|
/**
|
|
25
35
|
* Service do `@adonisjs/limiter` resolvido de forma preguiçosa. Tipado como `any`
|
|
@@ -90,5 +90,11 @@ export function createAuthThrottles(config) {
|
|
|
90
90
|
adminIp: buildThrottle('authkit_admin_ip', config.adminIp, config.store, (ctx) => {
|
|
91
91
|
return `admin-ip:${ctx.request.ip?.() ?? 'unknown'}`;
|
|
92
92
|
}),
|
|
93
|
+
// Rotas dos métodos de sudo: keyed por IP (default do HttpLimiter), igual ao
|
|
94
|
+
// login. O que separa os dois é o NOME do bucket — o limiter namespaceia a
|
|
95
|
+
// contagem por nome, então `authkit_login` e `authkit_sudo` nunca somam,
|
|
96
|
+
// mesmo vindo do mesmo IP. Sem `usingKey` próprio de propósito: inventar uma
|
|
97
|
+
// key aqui seria mudar o EIXO da contagem, e o eixo certo continua sendo o IP.
|
|
98
|
+
sudo: buildThrottle('authkit_sudo', config.sudo, config.store),
|
|
93
99
|
};
|
|
94
100
|
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { Router } from '@adonisjs/core/http';
|
|
2
2
|
import type { AuthSocialConfig, RateLimitConfigInput } from '../define_config.js';
|
|
3
|
+
import type { SudoMethod } from './sudo/types.js';
|
|
3
4
|
/** Chave da sessão Adonis que registra o timestamp da última atividade (idle timeout). */
|
|
4
5
|
export declare const ACCOUNT_LAST_SEEN_KEY = "authkit_last_seen";
|
|
5
6
|
/**
|
|
6
7
|
* Guard do console admin (B6). Como o `accountGuard`, é uma closure inline (forma
|
|
7
8
|
* confiável do `.use()` num grupo). Exige:
|
|
8
9
|
* 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
|
+
* 1. sessão de conta ativa (senão → `accountLoginUrl`, default /account/login);
|
|
10
11
|
* 2. a conta logada com pelo menos UMA das `config.admin.roles` nas roles globais
|
|
11
|
-
* (senão → /account/
|
|
12
|
+
* (senão → `accountHome(cfg)`, default /account/security — NÃO revela a
|
|
13
|
+
* existência do /admin, e cai numa tela que o host controla via `accountHome`;
|
|
14
|
+
* se a tela default estiver desmontada, aponte `config.accountHome` para uma montada).
|
|
12
15
|
* As roles permitidas são resolvidas em runtime do `authkit.server` (config lazy).
|
|
13
16
|
*/
|
|
14
17
|
export declare const adminGuard: (ctx: any, next: () => Promise<void>) => Promise<any>;
|
|
@@ -89,6 +92,86 @@ export interface AuthHostOptions {
|
|
|
89
92
|
adminApi?: boolean | {
|
|
90
93
|
prefix?: string;
|
|
91
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* Métodos de sudo cujas rotas devem ser montadas. Necessário aqui (e não só
|
|
97
|
+
* no config) porque a decisão de MONTAR rotas acontece em tempo de registro,
|
|
98
|
+
* antes de o config lazy resolver — mesma razão de `social`/`admin`/`rateLimit`.
|
|
99
|
+
* Espelhe o `sudo.methods` de config/authkit.ts.
|
|
100
|
+
*
|
|
101
|
+
* SUBSTITUI os defaults, não acrescenta: a lista é do host. Quem quer manter
|
|
102
|
+
* senha/passkey ao lado do método novo os inclui explicitamente
|
|
103
|
+
* (`[sudoMethods.password(), sudoMethods.passkey(), meuMetodo()]`).
|
|
104
|
+
*
|
|
105
|
+
* Sem esta opção, `config.sudo.methods` conseguiria OFERECER um método na
|
|
106
|
+
* tela mas nunca montar seu endpoint — a opção aparece e dá 404. Falha
|
|
107
|
+
* fechada, mas é a promessa do SPI pela metade; `magicLink()` em particular
|
|
108
|
+
* não teria como ser alcançado em runtime.
|
|
109
|
+
*
|
|
110
|
+
* Ausente → `[password(), passkey()]`.
|
|
111
|
+
*/
|
|
112
|
+
sudoMethods?: SudoMethod[];
|
|
113
|
+
/**
|
|
114
|
+
* Montagem por tela do console de conta (`/account/*`). Espelha o padrão
|
|
115
|
+
* `admin`/`adminApi`: a decisão de MONTAR cada grupo de rotas é tomada em
|
|
116
|
+
* tempo de registro, antes de o config (lazy) resolver.
|
|
117
|
+
*
|
|
118
|
+
* - Ausente → tudo montado (back-compat total).
|
|
119
|
+
* - `false` → NENHUMA tela do console de conta é montada (as rotas sudo
|
|
120
|
+
* `/account/confirm` e a JSON API `/account/api/*` continuam — são
|
|
121
|
+
* infraestrutura, não telas navegáveis).
|
|
122
|
+
* - objeto → montagem seletiva; cada flag ausente default `true`.
|
|
123
|
+
* - `login` → `/account/login`, `/account/logout` (a porta por senha do console).
|
|
124
|
+
* - `tokens` → `/account/tokens*` (Personal Access Tokens).
|
|
125
|
+
* - `orgs` → `/account/orgs*` (multi-tenancy, incl. o accept de convite público).
|
|
126
|
+
* - `security` → `/account/security*` + `/account/email/confirm` (perfil, senha, troca de e-mail, export/LGPD, deleção).
|
|
127
|
+
* - `mfa` → `/account/mfa*` (TOTP + passkeys).
|
|
128
|
+
* - `apps` → `/account/apps*` (grants de consentimento OIDC).
|
|
129
|
+
*
|
|
130
|
+
* NOTA (flag-drift): como `admin`/`adminApi`, estas flags controlam apenas se
|
|
131
|
+
* as ROTAS existem; o comportamento em runtime continua vindo do config
|
|
132
|
+
* resolvido. Mantenha em sincronia — os guards são a rede de segurança.
|
|
133
|
+
*
|
|
134
|
+
* ⚠️ Ao desmontar `login`, os redirects internos de "faça login"
|
|
135
|
+
* (`accountGuard`, `adminGuard`, `AccountAuthMiddleware`, `consoleLoginUrl()`,
|
|
136
|
+
* a view `otp-unlock`) apontariam para uma rota inexistente — passe
|
|
137
|
+
* `accountLoginUrl` com a rota de login do host (ex.: `'/login'`).
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* // Console passwordless: só segurança + MFA, login delegado ao OIDC do host.
|
|
141
|
+
* registerAuthHost(router, {
|
|
142
|
+
* account: { login: false, tokens: false, orgs: false },
|
|
143
|
+
* accountLoginUrl: '/login',
|
|
144
|
+
* })
|
|
145
|
+
*/
|
|
146
|
+
account?: false | AccountScreensOptions;
|
|
147
|
+
/**
|
|
148
|
+
* Destino do redirect de "não-autenticado → faça login" do console de conta.
|
|
149
|
+
* Default `/account/login`. Aponte para a rota de login do host quando a tela
|
|
150
|
+
* `account/login` da lib estiver desmontada (`account: { login: false }`).
|
|
151
|
+
*
|
|
152
|
+
* Usado por TODOS os pontos de redirect/link de login: `accountGuard`,
|
|
153
|
+
* `adminGuard`, `AccountAuthMiddleware`, `consoleLoginUrl()`, os fallbacks dos
|
|
154
|
+
* controllers de conta e a view `otp-unlock`. Ver `account_login_url.ts`.
|
|
155
|
+
*/
|
|
156
|
+
accountLoginUrl?: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Flags de montagem por tela do console de conta. Cada campo ausente é `true`
|
|
160
|
+
* (montado). Ver {@link AuthHostOptions.account}.
|
|
161
|
+
*/
|
|
162
|
+
export interface AccountScreensOptions {
|
|
163
|
+
/** Tela de login por senha do console (`/account/login`, `/account/logout`). */
|
|
164
|
+
login?: boolean;
|
|
165
|
+
/** Personal Access Tokens (`/account/tokens*`). */
|
|
166
|
+
tokens?: boolean;
|
|
167
|
+
/** Organizations / multi-tenancy (`/account/orgs*`). */
|
|
168
|
+
orgs?: boolean;
|
|
169
|
+
/** Perfil, senha, troca de e-mail, export/LGPD e deleção (`/account/security*`). */
|
|
170
|
+
security?: boolean;
|
|
171
|
+
/** MFA — TOTP + passkeys (`/account/mfa*`). */
|
|
172
|
+
mfa?: boolean;
|
|
173
|
+
/** Apps com acesso / grants de consentimento OIDC (`/account/apps*`). */
|
|
174
|
+
apps?: boolean;
|
|
92
175
|
}
|
|
93
176
|
/**
|
|
94
177
|
* Monta todas as rotas do host-kit do Authorization Server numa chamada.
|