@adonis-agora/authkit-server 0.57.0 → 0.57.1
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/README.md
CHANGED
|
@@ -31,7 +31,7 @@ node ace add @adonis-agora/authkit-server
|
|
|
31
31
|
# ou: pnpm add @adonis-agora/authkit-server && node ace configure @adonis-agora/authkit-server
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
O `configure` publica `config/
|
|
34
|
+
O `configure` publica `config/authkit.ts`, o model `app/models/auth_user.ts`,
|
|
35
35
|
o controller de interactions (`app/controllers/auth_interaction_controller.ts`) e
|
|
36
36
|
registra o provider.
|
|
37
37
|
|
|
@@ -89,7 +89,7 @@ Em todos os presets o controller ejetado é **casca**: a lógica vive em
|
|
|
89
89
|
`details(ctx)`, `login(ctx, { email, password })` e `consent(ctx)`. Você edita só a parte de
|
|
90
90
|
render/redirect.
|
|
91
91
|
|
|
92
|
-
Quem decide se as credenciais valem é o `verifyCredentials` do `config/
|
|
92
|
+
Quem decide se as credenciais valem é o `verifyCredentials` do `config/authkit.ts`
|
|
93
93
|
— é o que o `service.interactions.login` chama. O default consulta o `AuthUser` por e-mail e
|
|
94
94
|
usa `verifyPassword`; sobrescreva para plugar sua própria base de usuários.
|
|
95
95
|
|
|
@@ -105,7 +105,7 @@ router.post('/auth/interaction/:uid/consent', [AuthInteractionController, 'conse
|
|
|
105
105
|
|
|
106
106
|
## Persistência
|
|
107
107
|
|
|
108
|
-
Escolha o backend no `config/
|
|
108
|
+
Escolha o backend no `config/authkit.ts`:
|
|
109
109
|
- `adapters.redis({ connection })` — requer `@adonisjs/redis` configurado.
|
|
110
110
|
- `adapters.database({ connection? })` — Lucid; rode a migração `authkit_oidc_payloads`.
|
|
111
111
|
|
|
@@ -116,7 +116,7 @@ de resolve) e as expõe de forma opt-in.
|
|
|
116
116
|
|
|
117
117
|
### Configuração
|
|
118
118
|
|
|
119
|
-
No `config/
|
|
119
|
+
No `config/authkit.ts`, use a chave `observability`:
|
|
120
120
|
|
|
121
121
|
```ts
|
|
122
122
|
observability: {
|
|
@@ -131,6 +131,19 @@ export interface MailHooks {
|
|
|
131
131
|
unlockUrl: string;
|
|
132
132
|
token: string;
|
|
133
133
|
}) => Promise<void>;
|
|
134
|
+
/**
|
|
135
|
+
* Disparado pelo `authkit:expire-scan` quando uma conta está prestes a ser
|
|
136
|
+
* desativada por inatividade. Substitui o e-mail default de aviso quando
|
|
137
|
+
* fornecido. Best-effort, fire-and-forget; deduplicado pela janela de
|
|
138
|
+
* `warnDays` da setting `account_expiration`, então cada conta recebe no
|
|
139
|
+
* máximo um aviso por janela.
|
|
140
|
+
*/
|
|
141
|
+
onAccountExpirationWarning?: (data: {
|
|
142
|
+
/** E-mail da conta que será desativada. */
|
|
143
|
+
email: string;
|
|
144
|
+
/** Dias restantes até a desativação. */
|
|
145
|
+
expiresInDays: number;
|
|
146
|
+
}) => Promise<void>;
|
|
134
147
|
/**
|
|
135
148
|
* Disparado após um evento de segurança (senha alterada, MFA habilitado/desabilitado,
|
|
136
149
|
* passkey adicionada/removida, e-mail alterado). Substitui o e-mail default quando
|
|
@@ -888,15 +901,21 @@ export interface AuthServerConfigInput {
|
|
|
888
901
|
*/
|
|
889
902
|
accessTokens?: AccessTokensConfig;
|
|
890
903
|
/**
|
|
891
|
-
* Console admin do IdP (B6). Default: desligado.
|
|
892
|
-
*
|
|
893
|
-
*
|
|
904
|
+
* Console admin do IdP (B6). Default: desligado.
|
|
905
|
+
*
|
|
906
|
+
* Declarar esta chave TRAVA o liga/desliga: `registerAuthHost(router, { admin })`
|
|
907
|
+
* passa a ser ignorado (ver `deriveLockedRouteOptions`). Não repita o
|
|
908
|
+
* `enabled` no `start/routes.ts` — no máximo passe `admin: { prefix }`, que é
|
|
909
|
+
* estrutural e continua valendo.
|
|
894
910
|
*/
|
|
895
911
|
admin?: AdminConfigInput;
|
|
896
912
|
/**
|
|
897
|
-
* Admin REST API (R6). Default: desligada.
|
|
898
|
-
*
|
|
899
|
-
*
|
|
913
|
+
* Admin REST API (R6). Default: desligada. Autenticação por API key.
|
|
914
|
+
*
|
|
915
|
+
* Declarar esta chave TRAVA o liga/desliga: `registerAuthHost(router, { adminApi })`
|
|
916
|
+
* passa a ser ignorado (ver `deriveLockedRouteOptions`). Não repita o
|
|
917
|
+
* `enabled` no `start/routes.ts` — no máximo passe `adminApi: { prefix }`, que
|
|
918
|
+
* é estrutural e continua valendo.
|
|
900
919
|
*/
|
|
901
920
|
adminApi?: AdminApiConfigInput;
|
|
902
921
|
/**
|
|
@@ -913,8 +932,16 @@ export interface AuthServerConfigInput {
|
|
|
913
932
|
*/
|
|
914
933
|
resolveGeo?: ResolveGeo;
|
|
915
934
|
/**
|
|
916
|
-
* Gestão automática do schema das tabelas do authkit
|
|
917
|
-
* `auth_settings`, `auth_password_history
|
|
935
|
+
* Gestão automática do schema das OITO tabelas do authkit:
|
|
936
|
+
* `authkit_oidc_payloads`, `auth_settings`, `auth_password_history`,
|
|
937
|
+
* `auth_mfa`, `auth_session_revocations` e as três de organizations
|
|
938
|
+
* (`auth_organizations`, `auth_organization_members`,
|
|
939
|
+
* `auth_organization_invitations`). Ver `TABLES` em `schema/ensure.ts` — a
|
|
940
|
+
* lista aqui existe para o leitor, mas quem manda é aquele array.
|
|
941
|
+
*
|
|
942
|
+
* FORA desta gestão: `authkit_keystore`, criada sob demanda pelo
|
|
943
|
+
* `LucidKeystoreVault` na primeira escrita, e as tabelas do MODEL do host
|
|
944
|
+
* (`auth_users` etc.), que são migrations do app.
|
|
918
945
|
*
|
|
919
946
|
* - `autoManage` (default `true`): no boot, cria as tabelas que faltam e
|
|
920
947
|
* adiciona colunas novas (aditivo — nunca dropa nem altera tipos).
|
|
@@ -138,9 +138,11 @@ export declare function checkEmailChange(input: DoctorInput): Finding | null;
|
|
|
138
138
|
*/
|
|
139
139
|
export declare function checkSecurityNotifications(input: DoctorInput): Finding | null;
|
|
140
140
|
/**
|
|
141
|
-
* Verifica
|
|
142
|
-
* -
|
|
143
|
-
* -
|
|
141
|
+
* Verifica o pepper de senha (`accountStore.password.pepper`).
|
|
142
|
+
* - Silencioso quando não há pepper configurado.
|
|
143
|
+
* - Reporta o pepper como string e sugere a forma `[novo, antigo]`, que permite
|
|
144
|
+
* rotação sem downtime (lazy re-hash no verify).
|
|
145
|
+
* - Reporta quantos peppers a rotação tem quando já é array.
|
|
144
146
|
*/
|
|
145
147
|
export declare function checkPasswordPepper(input: DoctorInput): Finding | null;
|
|
146
148
|
/**
|
|
@@ -573,9 +573,11 @@ export function checkSecurityNotifications(input) {
|
|
|
573
573
|
return null; // Silencioso quando tudo está ok (não-obrigatório).
|
|
574
574
|
}
|
|
575
575
|
/**
|
|
576
|
-
* Verifica
|
|
577
|
-
* -
|
|
578
|
-
* -
|
|
576
|
+
* Verifica o pepper de senha (`accountStore.password.pepper`).
|
|
577
|
+
* - Silencioso quando não há pepper configurado.
|
|
578
|
+
* - Reporta o pepper como string e sugere a forma `[novo, antigo]`, que permite
|
|
579
|
+
* rotação sem downtime (lazy re-hash no verify).
|
|
580
|
+
* - Reporta quantos peppers a rotação tem quando já é array.
|
|
579
581
|
*/
|
|
580
582
|
export function checkPasswordPepper(input) {
|
|
581
583
|
const store = input.authkitConfig?.accountStore;
|
|
@@ -94,7 +94,7 @@ export class SettingLockedError extends Error {
|
|
|
94
94
|
code = 'E_SETTING_LOCKED';
|
|
95
95
|
key;
|
|
96
96
|
constructor(key) {
|
|
97
|
-
super(`
|
|
97
|
+
super(`The setting "${key}" is declared in defineConfig() and is therefore locked — it cannot be changed at runtime through the console or the Admin API. Remove it from defineConfig to hand the key back to the UI.`);
|
|
98
98
|
this.name = 'SettingLockedError';
|
|
99
99
|
this.key = key;
|
|
100
100
|
}
|
|
@@ -39,14 +39,23 @@ export interface AuthHostOptions {
|
|
|
39
39
|
* Login social opt-in; quando presente, monta as rotas sociais (usam ctx.ally).
|
|
40
40
|
* Necessário aqui (e não só no config) porque a decisão de montar as rotas é
|
|
41
41
|
* tomada em tempo de registro, antes do config (lazy) resolver.
|
|
42
|
+
*
|
|
43
|
+
* POLÍTICA: se o `defineConfig` declarou `social`, ele vence e este argumento
|
|
44
|
+
* é IGNORADO (com `console.warn` + entrada em `overriddenByConfig`). NÃO
|
|
45
|
+
* espelhe o config aqui — omitir a chave já herda dele. Use este argumento só
|
|
46
|
+
* quando o config NÃO declara `social`.
|
|
42
47
|
*/
|
|
43
48
|
social?: AuthSocialConfig;
|
|
44
49
|
/**
|
|
45
50
|
* Rate-limiting (anti-brute-force) das rotas sensíveis. Necessário aqui (e não
|
|
46
51
|
* só no config) porque a aplicação do throttle acontece em tempo de registro de
|
|
47
|
-
* rota. Ligado por default (mesma resolução do config).
|
|
48
|
-
* config/
|
|
49
|
-
* (
|
|
52
|
+
* rota. Ligado por default (mesma resolução do config). Se `@adonisjs/limiter`
|
|
53
|
+
* não estiver configurado no host (config/limiter.ts), o throttle vira no-op
|
|
54
|
+
* (fail-safe).
|
|
55
|
+
*
|
|
56
|
+
* POLÍTICA: se o `defineConfig` declarou `rateLimit`, ele vence e este
|
|
57
|
+
* argumento é IGNORADO (com `console.warn` + entrada em `overriddenByConfig`).
|
|
58
|
+
* NÃO espelhe o config aqui — omitir a chave já herda dele.
|
|
50
59
|
*/
|
|
51
60
|
rateLimit?: RateLimitConfigInput;
|
|
52
61
|
/**
|
|
@@ -60,7 +69,12 @@ export interface AuthHostOptions {
|
|
|
60
69
|
*
|
|
61
70
|
* Necessário aqui (e não só no config) porque a decisão de montar as rotas é
|
|
62
71
|
* tomada em tempo de registro, antes do config (lazy) resolver.
|
|
63
|
-
*
|
|
72
|
+
*
|
|
73
|
+
* DOIS EIXOS: o LIGA/DESLIGA é POLÍTICA — se o `defineConfig` declarou
|
|
74
|
+
* `admin`, ele vence e o `true`/`false` daqui é IGNORADO (com `console.warn`
|
|
75
|
+
* + entrada em `overriddenByConfig`). O PREFIXO é ESTRUTURAL e o argumento
|
|
76
|
+
* sempre vence. Ou seja: com `admin` no config, passe no máximo
|
|
77
|
+
* `{ prefix: '...' }` aqui — nunca espelhe o `enabled`.
|
|
64
78
|
*
|
|
65
79
|
* @example
|
|
66
80
|
* // Prefixo padrão
|
|
@@ -82,7 +96,11 @@ export interface AuthHostOptions {
|
|
|
82
96
|
*
|
|
83
97
|
* Necessário aqui (e não só no config) porque a decisão de montar as rotas é
|
|
84
98
|
* tomada em tempo de registro, antes do config (lazy) resolver.
|
|
85
|
-
*
|
|
99
|
+
*
|
|
100
|
+
* DOIS EIXOS, como `admin`: o LIGA/DESLIGA é POLÍTICA (o `defineConfig`
|
|
101
|
+
* vence e o argumento é IGNORADO, com `console.warn`), o PREFIXO é
|
|
102
|
+
* ESTRUTURAL (o argumento vence). Com `adminApi` no config, passe no máximo
|
|
103
|
+
* `{ prefix: '...' }` aqui.
|
|
86
104
|
*
|
|
87
105
|
* @example
|
|
88
106
|
* // Prefixo padrão (back-compat)
|
|
@@ -98,7 +116,10 @@ export interface AuthHostOptions {
|
|
|
98
116
|
* Métodos de sudo cujas rotas devem ser montadas. Necessário aqui (e não só
|
|
99
117
|
* no config) porque a decisão de MONTAR rotas acontece em tempo de registro,
|
|
100
118
|
* antes de o config lazy resolver — mesma razão de `social`/`admin`/`rateLimit`.
|
|
101
|
-
*
|
|
119
|
+
*
|
|
120
|
+
* POLÍTICA: se o `defineConfig` declarou `sudo.methods`, ele vence e este
|
|
121
|
+
* argumento é IGNORADO (com `console.warn` + entrada em `overriddenByConfig`).
|
|
122
|
+
* NÃO espelhe o config aqui — omitir a chave já herda dele.
|
|
102
123
|
*
|
|
103
124
|
* SUBSTITUI os defaults, não acrescenta: a lista é do host. Quem quer manter
|
|
104
125
|
* senha/passkey ao lado do método novo os inclui explicitamente
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonis-agora/authkit-server",
|
|
3
|
-
"version": "0.57.
|
|
3
|
+
"version": "0.57.1",
|
|
4
4
|
"description": "AdonisJS OIDC/OAuth2 provider (Identity Provider) toolkit: ejectable auth server with sessions, rate-limiting, MFA/TOTP, audit log, federated logout and OpenTelemetry metrics.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "dudousxd",
|
|
7
|
-
"homepage": "https://github.com/DavideCarvalho/adonis-authkit/tree/main/packages/authkit-server#readme",
|
|
7
|
+
"homepage": "https://github.com/DavideCarvalho/adonis-agora-authkit/tree/main/packages/authkit-server#readme",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/DavideCarvalho/adonis-agora-authkit.git",
|
|
11
11
|
"directory": "packages/authkit-server"
|
|
12
12
|
},
|
|
13
13
|
"bugs": {
|
|
14
|
-
"url": "https://github.com/DavideCarvalho/adonis-authkit/issues"
|
|
14
|
+
"url": "https://github.com/DavideCarvalho/adonis-agora-authkit/issues"
|
|
15
15
|
},
|
|
16
16
|
"keywords": [
|
|
17
17
|
"adonisjs",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
"oidc-provider": "9.11.3",
|
|
109
109
|
"otplib": "12.0.1",
|
|
110
110
|
"qrcode": "1.5.4",
|
|
111
|
-
"@adonis-agora/authkit-core": "0.7.
|
|
111
|
+
"@adonis-agora/authkit-core": "0.7.1"
|
|
112
112
|
},
|
|
113
113
|
"devDependencies": {
|
|
114
114
|
"@adonis-agora/durable": "0.22.0",
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"react-error-boundary": "6.1.2",
|
|
151
151
|
"nuqs": "2.9.5",
|
|
152
152
|
"recharts": "3.10.1",
|
|
153
|
-
"@adonis-agora/authkit-react": "0.18.
|
|
153
|
+
"@adonis-agora/authkit-react": "0.18.1"
|
|
154
154
|
},
|
|
155
155
|
"scripts": {
|
|
156
156
|
"build": "node scripts/build_host_css.mjs && node scripts/build_webauthn.mjs && node scripts/build_ui.mjs && node -e \"const fs=require('node:fs');for(const d of ['build/stubs','build/host/views'])fs.rmSync(d,{recursive:true,force:true})\" && tsc && node -e \"require('node:fs').cpSync('src/host/assets','build/src/host/assets',{recursive:true})\" && node -e \"require('node:fs').cpSync('stubs','build/stubs',{recursive:true,filter:(s)=>!s.endsWith('.ts')})\" && node -e \"const fs=require('node:fs');if(fs.existsSync('assets'))fs.cpSync('assets','build/assets',{recursive:true})\" && node -e \"require('node:fs').cpSync('src/host/views','build/host/views',{recursive:true})\" && node -e \"const fs=require('node:fs');fs.mkdirSync('build/host/ui',{recursive:true});fs.readdirSync('src/host/ui').filter(f=>f.endsWith('.html')).forEach(f=>fs.copyFileSync('src/host/ui/'+f,'build/host/ui/'+f))\" && node -e \"require('node:fs').copyFileSync('commands/commands.json','build/commands/commands.json')\" && node -e \"const fs=require('node:fs');fs.mkdirSync('build/src/password',{recursive:true});fs.copyFileSync('src/password/common_passwords.txt','build/src/password/common_passwords.txt')\"",
|