@dudousxd/adonis-authkit-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +137 -0
- package/build/assets/grafana/authkit-dashboard.json +118 -0
- package/build/commands/commands.json +30 -0
- package/build/commands/configure.d.ts +2 -0
- package/build/commands/configure.js +42 -0
- package/build/commands/eject.d.ts +11 -0
- package/build/commands/eject.js +96 -0
- package/build/commands/main.d.ts +12 -0
- package/build/commands/main.js +38 -0
- package/build/commands/ui_preset.d.ts +4 -0
- package/build/commands/ui_preset.js +32 -0
- package/build/database/migrations/make_authkit_oidc_table.d.ts +6 -0
- package/build/database/migrations/make_authkit_oidc_table.js +19 -0
- package/build/host/views/account/login.edge +29 -0
- package/build/host/views/account/mfa.edge +151 -0
- package/build/host/views/account/tokens.edge +70 -0
- package/build/host/views/admin/audit.edge +72 -0
- package/build/host/views/admin/clients.edge +51 -0
- package/build/host/views/admin/dashboard.edge +58 -0
- package/build/host/views/admin/users.edge +76 -0
- package/build/host/views/consent.edge +19 -0
- package/build/host/views/forgot.edge +30 -0
- package/build/host/views/login.edge +91 -0
- package/build/host/views/mfa-challenge.edge +88 -0
- package/build/host/views/reset.edge +29 -0
- package/build/host/views/signup.edge +44 -0
- package/build/host/views/verify-email.edge +16 -0
- package/build/index.d.ts +42 -0
- package/build/index.js +28 -0
- package/build/providers/authkit_server_provider.d.ts +19 -0
- package/build/providers/authkit_server_provider.js +81 -0
- package/build/src/accounts/account_store.d.ts +136 -0
- package/build/src/accounts/account_store.js +1 -0
- package/build/src/accounts/lucid_account_store.d.ts +75 -0
- package/build/src/accounts/lucid_account_store.js +396 -0
- package/build/src/adapters/adapter_contract.d.ts +18 -0
- package/build/src/adapters/adapter_contract.js +1 -0
- package/build/src/adapters/database_adapter.d.ts +15 -0
- package/build/src/adapters/database_adapter.js +63 -0
- package/build/src/adapters/factory.d.ts +30 -0
- package/build/src/adapters/factory.js +43 -0
- package/build/src/adapters/redis_adapter.d.ts +16 -0
- package/build/src/adapters/redis_adapter.js +95 -0
- package/build/src/audit/audit_sink.d.ts +54 -0
- package/build/src/audit/audit_sink.js +1 -0
- package/build/src/audit/lucid_audit_sink.d.ts +10 -0
- package/build/src/audit/lucid_audit_sink.js +60 -0
- package/build/src/controllers/oidc_callback_controller.d.ts +22 -0
- package/build/src/controllers/oidc_callback_controller.js +33 -0
- package/build/src/define_config.d.ts +261 -0
- package/build/src/define_config.js +115 -0
- package/build/src/host/account_lockout.d.ts +86 -0
- package/build/src/host/account_lockout.js +185 -0
- package/build/src/host/augmentations.d.ts +1 -0
- package/build/src/host/augmentations.js +1 -0
- package/build/src/host/branding.d.ts +17 -0
- package/build/src/host/branding.js +8 -0
- package/build/src/host/controllers/account_mfa_controller.d.ts +30 -0
- package/build/src/host/controllers/account_mfa_controller.js +157 -0
- package/build/src/host/controllers/account_session_controller.d.ts +7 -0
- package/build/src/host/controllers/account_session_controller.js +50 -0
- package/build/src/host/controllers/account_tokens_controller.d.ts +7 -0
- package/build/src/host/controllers/account_tokens_controller.js +55 -0
- package/build/src/host/controllers/admin/admin_audit_controller.d.ts +10 -0
- package/build/src/host/controllers/admin/admin_audit_controller.js +56 -0
- package/build/src/host/controllers/admin/admin_clients_controller.d.ts +10 -0
- package/build/src/host/controllers/admin/admin_clients_controller.js +24 -0
- package/build/src/host/controllers/admin/admin_dashboard_controller.d.ts +10 -0
- package/build/src/host/controllers/admin/admin_dashboard_controller.js +27 -0
- package/build/src/host/controllers/admin/admin_users_controller.d.ts +11 -0
- package/build/src/host/controllers/admin/admin_users_controller.js +53 -0
- package/build/src/host/controllers/interaction_controller.d.ts +44 -0
- package/build/src/host/controllers/interaction_controller.js +304 -0
- package/build/src/host/controllers/pat_introspection_controller.d.ts +22 -0
- package/build/src/host/controllers/pat_introspection_controller.js +46 -0
- package/build/src/host/controllers/registration_controller.d.ts +18 -0
- package/build/src/host/controllers/registration_controller.js +169 -0
- package/build/src/host/controllers/social_controller.d.ts +8 -0
- package/build/src/host/controllers/social_controller.js +82 -0
- package/build/src/host/default_mailer.d.ts +39 -0
- package/build/src/host/default_mailer.js +141 -0
- package/build/src/host/email_templates.d.ts +35 -0
- package/build/src/host/email_templates.js +66 -0
- package/build/src/host/i18n.d.ts +178 -0
- package/build/src/host/i18n.js +208 -0
- package/build/src/host/middleware/account_auth.d.ts +7 -0
- package/build/src/host/middleware/account_auth.js +11 -0
- package/build/src/host/rate_limit.d.ts +32 -0
- package/build/src/host/rate_limit.js +87 -0
- package/build/src/host/register_auth_host.d.ts +41 -0
- package/build/src/host/register_auth_host.js +133 -0
- package/build/src/host/renderers/edge_renderer.d.ts +3 -0
- package/build/src/host/renderers/edge_renderer.js +29 -0
- package/build/src/host/renderers/inertia_renderer.d.ts +5 -0
- package/build/src/host/renderers/inertia_renderer.js +26 -0
- package/build/src/host/validators.d.ts +39 -0
- package/build/src/host/validators.js +13 -0
- package/build/src/keys/jwks_manager.d.ts +6 -0
- package/build/src/keys/jwks_manager.js +11 -0
- package/build/src/mixins/with_audit_log.d.ts +19 -0
- package/build/src/mixins/with_audit_log.js +41 -0
- package/build/src/mixins/with_auth_user.d.ts +18 -0
- package/build/src/mixins/with_auth_user.js +39 -0
- package/build/src/mixins/with_credentials.d.ts +20 -0
- package/build/src/mixins/with_credentials.js +29 -0
- package/build/src/mixins/with_mfa.d.ts +31 -0
- package/build/src/mixins/with_mfa.js +39 -0
- package/build/src/mixins/with_personal_access_token.d.ts +19 -0
- package/build/src/mixins/with_personal_access_token.js +44 -0
- package/build/src/mixins/with_provider_identity.d.ts +20 -0
- package/build/src/mixins/with_provider_identity.js +32 -0
- package/build/src/mixins/with_webauthn_credential.d.ts +37 -0
- package/build/src/mixins/with_webauthn_credential.js +49 -0
- package/build/src/observability/metrics_controller.d.ts +5 -0
- package/build/src/observability/metrics_controller.js +24 -0
- package/build/src/observability/metrics_service.d.ts +2 -0
- package/build/src/observability/metrics_service.js +7 -0
- package/build/src/observability/otel_recorder.d.ts +10 -0
- package/build/src/observability/otel_recorder.js +59 -0
- package/build/src/observability/wire_provider_events.d.ts +12 -0
- package/build/src/observability/wire_provider_events.js +19 -0
- package/build/src/pat/lucid_pat_store.d.ts +6 -0
- package/build/src/pat/lucid_pat_store.js +62 -0
- package/build/src/pat/pat_store.d.ts +31 -0
- package/build/src/pat/pat_store.js +1 -0
- package/build/src/pat/pat_tokens.d.ts +4 -0
- package/build/src/pat/pat_tokens.js +9 -0
- package/build/src/provider/build_provider.d.ts +8 -0
- package/build/src/provider/build_provider.js +101 -0
- package/build/src/provider/interaction_actions.d.ts +21 -0
- package/build/src/provider/interaction_actions.js +32 -0
- package/build/src/provider/oidc_service.d.ts +17 -0
- package/build/src/provider/oidc_service.js +84 -0
- package/build/src/provider/token_exchange.d.ts +15 -0
- package/build/src/provider/token_exchange.js +72 -0
- package/build/src/register_routes.d.ts +16 -0
- package/build/src/register_routes.js +21 -0
- package/build/stubs/config/authkit.stub +29 -0
- package/build/stubs/main.d.ts +1 -0
- package/build/stubs/main.js +2 -0
- package/build/stubs/models/auth_user.stub +13 -0
- package/build/stubs/ui/edge/views/consent.edge +13 -0
- package/build/stubs/ui/edge/views/login.edge +19 -0
- package/build/stubs/ui/react/components/auth_shell.tsx +67 -0
- package/build/stubs/ui/react/pages/account/login.tsx +56 -0
- package/build/stubs/ui/react/pages/account/mfa.tsx +132 -0
- package/build/stubs/ui/react/pages/account/tokens.tsx +88 -0
- package/build/stubs/ui/react/pages/consent.tsx +39 -0
- package/build/stubs/ui/react/pages/forgot.tsx +44 -0
- package/build/stubs/ui/react/pages/login.tsx +171 -0
- package/build/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
- package/build/stubs/ui/react/pages/reset.tsx +58 -0
- package/build/stubs/ui/react/pages/signup.tsx +78 -0
- package/build/stubs/ui/react/pages/verify-email.tsx +24 -0
- package/build/types.d.ts +7 -0
- package/build/types.js +1 -0
- package/package.json +108 -0
- package/stubs/config/authkit.stub +29 -0
- package/stubs/main.ts +2 -0
- package/stubs/models/auth_user.stub +13 -0
- package/stubs/ui/edge/views/consent.edge +13 -0
- package/stubs/ui/edge/views/login.edge +19 -0
- package/stubs/ui/react/components/auth_shell.tsx +67 -0
- package/stubs/ui/react/pages/account/login.tsx +56 -0
- package/stubs/ui/react/pages/account/mfa.tsx +132 -0
- package/stubs/ui/react/pages/account/tokens.tsx +88 -0
- package/stubs/ui/react/pages/consent.tsx +39 -0
- package/stubs/ui/react/pages/forgot.tsx +44 -0
- package/stubs/ui/react/pages/login.tsx +171 -0
- package/stubs/ui/react/pages/mfa-challenge.tsx +72 -0
- package/stubs/ui/react/pages/reset.tsx +58 -0
- package/stubs/ui/react/pages/signup.tsx +78 -0
- package/stubs/ui/react/pages/verify-email.tsx +24 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('mfa_challenge.page_title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
|
|
3
|
+
<script src="https://cdn.tailwindcss.com"></script></head>
|
|
4
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
5
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
6
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/mfa">
|
|
7
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
8
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('mfa_challenge.title') }}</h1>
|
|
9
|
+
<p class="mt-1 text-sm text-gray-500">
|
|
10
|
+
{{ t('mfa_challenge.intro') }}
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
@if(error)
|
|
14
|
+
<p class="mt-4 text-sm text-red-600">{{ error }}</p>
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
<div class="mt-6">
|
|
18
|
+
<label for="code" class="mb-1 block text-sm font-medium text-gray-700">{{ t('mfa_challenge.code_label') }}</label>
|
|
19
|
+
<input id="code" name="code" inputmode="numeric" autocomplete="one-time-code"
|
|
20
|
+
pattern="[0-9]*" maxlength="6" autofocus
|
|
21
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-center text-lg tracking-[0.4em] outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<button type="submit"
|
|
25
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
26
|
+
{{ t('mfa_challenge.submit') }}
|
|
27
|
+
</button>
|
|
28
|
+
</form>
|
|
29
|
+
|
|
30
|
+
@if(passkeyAvailable)
|
|
31
|
+
{{-- Passkey como alternativa ao código TOTP. O form é submetido por página
|
|
32
|
+
inteira (não fetch) para que o 303 de volta ao client navegue o browser. --}}
|
|
33
|
+
<form id="passkey-form" method="POST" action="/auth/interaction/{{ uid }}/passkey/verify" class="mt-4">
|
|
34
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
35
|
+
<input type="hidden" name="response" id="passkey-response">
|
|
36
|
+
</form>
|
|
37
|
+
<button type="button" id="passkey-button"
|
|
38
|
+
class="mt-4 w-full rounded-lg border border-gray-300 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50">
|
|
39
|
+
{{ t('mfa_challenge.passkey_button') }}
|
|
40
|
+
</button>
|
|
41
|
+
<p id="passkey-error" class="mt-3 hidden text-sm text-red-600">{{ t('mfa_challenge.passkey_error') }}</p>
|
|
42
|
+
@end
|
|
43
|
+
|
|
44
|
+
<details class="mt-6 text-sm text-gray-600">
|
|
45
|
+
<summary class="cursor-pointer hover:underline">{{ t('mfa_challenge.recovery_summary') }}</summary>
|
|
46
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/mfa" class="mt-3">
|
|
47
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
48
|
+
<input name="recoveryCode" placeholder="xxxxx-xxxxx"
|
|
49
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none focus:border-gray-900" />
|
|
50
|
+
<button type="submit"
|
|
51
|
+
class="mt-3 w-full rounded-lg border border-gray-300 py-2.5 text-sm font-semibold text-gray-700 transition hover:bg-gray-50">
|
|
52
|
+
{{ t('mfa_challenge.recovery_submit') }}
|
|
53
|
+
</button>
|
|
54
|
+
</form>
|
|
55
|
+
</details>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
@if(passkeyAvailable)
|
|
59
|
+
<script type="module">
|
|
60
|
+
import { startAuthentication } from 'https://cdn.jsdelivr.net/npm/@simplewebauthn/browser@13/dist/bundle/index.js'
|
|
61
|
+
const btn = document.getElementById('passkey-button')
|
|
62
|
+
const errEl = document.getElementById('passkey-error')
|
|
63
|
+
const csrf = document.querySelector('#passkey-form input[name="_csrf"]').value
|
|
64
|
+
btn?.addEventListener('click', async () => {
|
|
65
|
+
errEl.classList.add('hidden')
|
|
66
|
+
btn.disabled = true
|
|
67
|
+
try {
|
|
68
|
+
// 1) Busca as opções de autenticação (challenge guardado na sessão server-side).
|
|
69
|
+
const res = await fetch('/auth/interaction/{{ uid }}/passkey/options', {
|
|
70
|
+
method: 'POST',
|
|
71
|
+
headers: { 'content-type': 'application/json', 'x-csrf-token': csrf },
|
|
72
|
+
body: JSON.stringify({}),
|
|
73
|
+
})
|
|
74
|
+
if (!res.ok) throw new Error('options')
|
|
75
|
+
const optionsJSON = await res.json()
|
|
76
|
+
// 2) Cerimônia no authenticator.
|
|
77
|
+
const assertion = await startAuthentication({ optionsJSON })
|
|
78
|
+
// 3) Submete a assertion como POST de página inteira (segue o 303).
|
|
79
|
+
document.getElementById('passkey-response').value = JSON.stringify(assertion)
|
|
80
|
+
document.getElementById('passkey-form').submit()
|
|
81
|
+
} catch (e) {
|
|
82
|
+
errEl.classList.remove('hidden')
|
|
83
|
+
btn.disabled = false
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
</script>
|
|
87
|
+
@end
|
|
88
|
+
</body></html>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('reset.page_title') }}</title>
|
|
3
|
+
<script src="https://cdn.tailwindcss.com"></script></head>
|
|
4
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
5
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
6
|
+
@if(done)
|
|
7
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('reset.done_title') }}</h1>
|
|
8
|
+
<p class="mt-2 text-sm text-gray-600">{{ t('reset.done_body') }}</p>
|
|
9
|
+
@else
|
|
10
|
+
<form method="POST" action="/auth/reset-password">
|
|
11
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
12
|
+
<input type="hidden" name="token" value="{{ token }}">
|
|
13
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('reset.title') }}</h1>
|
|
14
|
+
<p class="mt-1 text-sm text-gray-500">{{ t('reset.intro') }}</p>
|
|
15
|
+
|
|
16
|
+
<div class="mt-6">
|
|
17
|
+
<label for="password" class="mb-1 block text-sm font-medium text-gray-700">{{ t('reset.password_label') }}</label>
|
|
18
|
+
<input id="password" name="password" type="password" required minlength="8"
|
|
19
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<button type="submit"
|
|
23
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
24
|
+
{{ t('reset.submit') }}
|
|
25
|
+
</button>
|
|
26
|
+
</form>
|
|
27
|
+
@end
|
|
28
|
+
</div>
|
|
29
|
+
</body></html>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('signup.page_title') }} — {{ brand && brand.appName ? brand.appName : t('common.app_fallback') }}</title>
|
|
3
|
+
<script src="https://cdn.tailwindcss.com"></script></head>
|
|
4
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
5
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
6
|
+
<form method="POST" action="/auth/interaction/{{ uid }}/signup">
|
|
7
|
+
<input type="hidden" name="_csrf" value="{{ csrfToken }}">
|
|
8
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('signup.title') }}</h1>
|
|
9
|
+
<p class="mt-1 text-sm text-gray-500">{{ t('signup.intro') }}</p>
|
|
10
|
+
|
|
11
|
+
@if(error)
|
|
12
|
+
<p class="mt-4 text-sm text-red-600">{{ error }}</p>
|
|
13
|
+
@end
|
|
14
|
+
|
|
15
|
+
<div class="mt-6">
|
|
16
|
+
<label for="fullName" class="mb-1 block text-sm font-medium text-gray-700">{{ t('signup.name_label') }}</label>
|
|
17
|
+
<input id="fullName" name="fullName" type="text" required
|
|
18
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div class="mt-4">
|
|
22
|
+
<label for="email" class="mb-1 block text-sm font-medium text-gray-700">{{ t('signup.email_label') }}</label>
|
|
23
|
+
<input id="email" name="email" type="email" required
|
|
24
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="mt-4">
|
|
28
|
+
<label for="password" class="mb-1 block text-sm font-medium text-gray-700">{{ t('signup.password_label') }}</label>
|
|
29
|
+
<input id="password" name="password" type="password" required minlength="8"
|
|
30
|
+
class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm outline-none transition focus:border-gray-900 focus:ring-2 focus:ring-gray-900" />
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<button type="submit"
|
|
34
|
+
class="mt-6 w-full rounded-lg bg-gray-900 py-2.5 text-sm font-semibold text-white transition hover:opacity-90">
|
|
35
|
+
{{ t('signup.submit') }}
|
|
36
|
+
</button>
|
|
37
|
+
|
|
38
|
+
<a href="/auth/interaction/{{ uid }}"
|
|
39
|
+
class="mt-4 block text-center text-sm text-gray-600 hover:underline">
|
|
40
|
+
{{ t('signup.have_account') }}
|
|
41
|
+
</a>
|
|
42
|
+
</form>
|
|
43
|
+
</div>
|
|
44
|
+
</body></html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="pt-br"><head><meta charset="utf-8"><title>{{ t('verify_email.page_title') }}</title>
|
|
3
|
+
<script src="https://cdn.tailwindcss.com"></script></head>
|
|
4
|
+
<body class="min-h-screen flex items-center justify-center bg-gray-50">
|
|
5
|
+
<div class="w-full max-w-sm bg-white p-8 rounded-2xl shadow-xl ring-1 ring-black/5">
|
|
6
|
+
@if(verified)
|
|
7
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('verify_email.verified_title') }}</h1>
|
|
8
|
+
<p class="mt-2 text-sm text-gray-600">{{ t('verify_email.verified_body') }}</p>
|
|
9
|
+
@else
|
|
10
|
+
<h1 class="text-xl font-semibold text-gray-900">{{ t('verify_email.invalid_title') }}</h1>
|
|
11
|
+
<p class="mt-2 text-sm text-gray-600">
|
|
12
|
+
{{ t('verify_email.invalid_body') }}
|
|
13
|
+
</p>
|
|
14
|
+
@end
|
|
15
|
+
</div>
|
|
16
|
+
</body></html>
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export { defineConfig, adapters, toSeconds } from './src/define_config.js';
|
|
2
|
+
export { generatePatToken, hashPatToken } from './src/pat/pat_tokens.js';
|
|
3
|
+
export { withAuthUser } from './src/mixins/with_auth_user.js';
|
|
4
|
+
export { withCredentials } from './src/mixins/with_credentials.js';
|
|
5
|
+
export { withMfa } from './src/mixins/with_mfa.js';
|
|
6
|
+
export { OidcService } from './src/provider/oidc_service.js';
|
|
7
|
+
export { registerOidcRoutes } from './src/register_routes.js';
|
|
8
|
+
export type { AuthServerConfigInput, ResolvedServerConfig, DynamicRegistrationConfigInput, ResolvedDynamicRegistrationConfig, AdminConfigInput, ResolvedAdminConfig, } from './src/define_config.js';
|
|
9
|
+
export { resolveAdmin, resolveWebauthn } from './src/define_config.js';
|
|
10
|
+
export type { WebauthnConfigInput, ResolvedWebauthnConfig } from './src/define_config.js';
|
|
11
|
+
export { lucidAccountStore } from './src/accounts/lucid_account_store.js';
|
|
12
|
+
export type { LucidAccountStoreOptions, AccountSecretEncrypter, } from './src/accounts/lucid_account_store.js';
|
|
13
|
+
export type { AccountStore, AuthAccount, CreateAccountInput, LinkProviderIdentityInput, ListAccountsParams, Paginated, PasskeySummary, } from './src/accounts/account_store.js';
|
|
14
|
+
export { withProviderIdentity } from './src/mixins/with_provider_identity.js';
|
|
15
|
+
export type { ProviderIdentityRow, ProviderIdentityClass, } from './src/mixins/with_provider_identity.js';
|
|
16
|
+
export { withWebauthnCredential } from './src/mixins/with_webauthn_credential.js';
|
|
17
|
+
export type { WebauthnCredentialRow, WebauthnCredentialClass, } from './src/mixins/with_webauthn_credential.js';
|
|
18
|
+
export { lucidPatStore } from './src/pat/lucid_pat_store.js';
|
|
19
|
+
export type { PatStore, PatRecord, IssuePatInput } from './src/pat/pat_store.js';
|
|
20
|
+
export { withPersonalAccessToken } from './src/mixins/with_personal_access_token.js';
|
|
21
|
+
export { lucidAuditSink } from './src/audit/lucid_audit_sink.js';
|
|
22
|
+
export type { AuditSink, AuditEvent, AuditEventType, StoredAuditEvent, ListAuditParams, AuditPage, } from './src/audit/audit_sink.js';
|
|
23
|
+
export { withAuditLog } from './src/mixins/with_audit_log.js';
|
|
24
|
+
export { inertiaRenderer } from './src/host/renderers/inertia_renderer.js';
|
|
25
|
+
export { edgeRenderer } from './src/host/renderers/edge_renderer.js';
|
|
26
|
+
export { brandFor, isFirstParty } from './src/host/branding.js';
|
|
27
|
+
export type { BrandingConfig, ClientBrand } from './src/host/branding.js';
|
|
28
|
+
export { resolveMessages, translate, DEFAULT_MESSAGES, DEFAULT_LOCALE } from './src/host/i18n.js';
|
|
29
|
+
export type { I18nConfig, AuthMessages } from './src/host/i18n.js';
|
|
30
|
+
export type { AuthHostRenderer, AuthSocialConfig } from './src/define_config.js';
|
|
31
|
+
export { registerAuthHost } from './src/host/register_auth_host.js';
|
|
32
|
+
export type { AuthHostOptions } from './src/host/register_auth_host.js';
|
|
33
|
+
export { resolveRateLimit } from './src/define_config.js';
|
|
34
|
+
export type { RateLimitConfigInput, RateLimitBucket, ResolvedRateLimitConfig, } from './src/define_config.js';
|
|
35
|
+
export { createAuthThrottles } from './src/host/rate_limit.js';
|
|
36
|
+
export type { AuthThrottles, ThrottleMiddleware } from './src/host/rate_limit.js';
|
|
37
|
+
/**
|
|
38
|
+
* Configure hook + stubsRoot resolvidos pelo `node ace configure @dudousxd/adonis-authkit-server`.
|
|
39
|
+
* O comando do AdonisJS importa o entrypoint principal e procura por estes exports.
|
|
40
|
+
*/
|
|
41
|
+
export { configure } from './commands/configure.js';
|
|
42
|
+
export { stubsRoot } from './stubs/main.js';
|
package/build/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export { defineConfig, adapters, toSeconds } from './src/define_config.js';
|
|
2
|
+
export { generatePatToken, hashPatToken } from './src/pat/pat_tokens.js';
|
|
3
|
+
export { withAuthUser } from './src/mixins/with_auth_user.js';
|
|
4
|
+
export { withCredentials } from './src/mixins/with_credentials.js';
|
|
5
|
+
export { withMfa } from './src/mixins/with_mfa.js';
|
|
6
|
+
export { OidcService } from './src/provider/oidc_service.js';
|
|
7
|
+
export { registerOidcRoutes } from './src/register_routes.js';
|
|
8
|
+
export { resolveAdmin, resolveWebauthn } from './src/define_config.js';
|
|
9
|
+
export { lucidAccountStore } from './src/accounts/lucid_account_store.js';
|
|
10
|
+
export { withProviderIdentity } from './src/mixins/with_provider_identity.js';
|
|
11
|
+
export { withWebauthnCredential } from './src/mixins/with_webauthn_credential.js';
|
|
12
|
+
export { lucidPatStore } from './src/pat/lucid_pat_store.js';
|
|
13
|
+
export { withPersonalAccessToken } from './src/mixins/with_personal_access_token.js';
|
|
14
|
+
export { lucidAuditSink } from './src/audit/lucid_audit_sink.js';
|
|
15
|
+
export { withAuditLog } from './src/mixins/with_audit_log.js';
|
|
16
|
+
export { inertiaRenderer } from './src/host/renderers/inertia_renderer.js';
|
|
17
|
+
export { edgeRenderer } from './src/host/renderers/edge_renderer.js';
|
|
18
|
+
export { brandFor, isFirstParty } from './src/host/branding.js';
|
|
19
|
+
export { resolveMessages, translate, DEFAULT_MESSAGES, DEFAULT_LOCALE } from './src/host/i18n.js';
|
|
20
|
+
export { registerAuthHost } from './src/host/register_auth_host.js';
|
|
21
|
+
export { resolveRateLimit } from './src/define_config.js';
|
|
22
|
+
export { createAuthThrottles } from './src/host/rate_limit.js';
|
|
23
|
+
/**
|
|
24
|
+
* Configure hook + stubsRoot resolvidos pelo `node ace configure @dudousxd/adonis-authkit-server`.
|
|
25
|
+
* O comando do AdonisJS importa o entrypoint principal e procura por estes exports.
|
|
26
|
+
*/
|
|
27
|
+
export { configure } from './commands/configure.js';
|
|
28
|
+
export { stubsRoot } from './stubs/main.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
2
|
+
import type { MetricsRecorder } from '@dudousxd/adonis-authkit-core';
|
|
3
|
+
import { OidcService } from '../src/provider/oidc_service.js';
|
|
4
|
+
import type { AccountStore } from '../src/accounts/account_store.js';
|
|
5
|
+
import type { PatStore } from '../src/pat/pat_store.js';
|
|
6
|
+
declare module '@adonisjs/core/types' {
|
|
7
|
+
interface ContainerBindings {
|
|
8
|
+
'authkit.server': OidcService;
|
|
9
|
+
'authkit.metrics': MetricsRecorder;
|
|
10
|
+
'authkit.accountStore': AccountStore;
|
|
11
|
+
'authkit.patStore': PatStore;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export default class AuthkitServerProvider {
|
|
15
|
+
protected app: ApplicationService;
|
|
16
|
+
constructor(app: ApplicationService);
|
|
17
|
+
boot(): Promise<void>;
|
|
18
|
+
register(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { configProvider } from '@adonisjs/core';
|
|
4
|
+
import { RuntimeException } from '@adonisjs/core/exceptions';
|
|
5
|
+
import { OidcService } from '../src/provider/oidc_service.js';
|
|
6
|
+
export default class AuthkitServerProvider {
|
|
7
|
+
app;
|
|
8
|
+
constructor(app) {
|
|
9
|
+
this.app = app;
|
|
10
|
+
}
|
|
11
|
+
async boot() {
|
|
12
|
+
// Registra o disco "authkit" no edge.js para que os templates sejam referenciados
|
|
13
|
+
// como `authkit::login`, `authkit::account/tokens`, etc.
|
|
14
|
+
// Resolve o diretório das views tanto em produção (provider compilado em
|
|
15
|
+
// `build/providers/`, views copiadas para `build/host/views`) quanto em dev
|
|
16
|
+
// (rodando de `providers/` via ts-exec; views em `build/host/views` após build
|
|
17
|
+
// ou em `src/host/views` sem build).
|
|
18
|
+
const candidates = [
|
|
19
|
+
new URL('../host/views', import.meta.url), // prod: build/providers → build/host/views
|
|
20
|
+
new URL('../build/host/views', import.meta.url), // dev: providers → build/host/views
|
|
21
|
+
new URL('../src/host/views', import.meta.url), // dev sem build: providers → src/host/views
|
|
22
|
+
];
|
|
23
|
+
const viewsUrl = candidates.find((u) => existsSync(fileURLToPath(u)));
|
|
24
|
+
if (!viewsUrl)
|
|
25
|
+
return; // nenhum dir de views resolvível
|
|
26
|
+
try {
|
|
27
|
+
const edge = await import('edge.js');
|
|
28
|
+
const edgeInstance = edge.default ?? edge;
|
|
29
|
+
edgeInstance.mount('authkit', viewsUrl);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// edge.js ausente (host headless/Inertia-only que não usa edgeRenderer) — ignora.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
register() {
|
|
36
|
+
this.app.container.singleton('authkit.server', async () => {
|
|
37
|
+
const configProviderValue = this.app.config.get('authkit');
|
|
38
|
+
const config = (await configProvider.resolve(this.app, configProviderValue));
|
|
39
|
+
if (!config) {
|
|
40
|
+
throw new RuntimeException('Config inválido em "config/authkit.ts". Use o método defineConfig de @dudousxd/adonis-authkit-server.');
|
|
41
|
+
}
|
|
42
|
+
// `app.appKey` pode ser uma string crua ou um `Secret` do AdonisJS (config/app.ts
|
|
43
|
+
// expõe `export const appKey = new Secret(env.get('APP_KEY'))`). O oidc-provider
|
|
44
|
+
// assina cookies via keygrip e exige uma string — então liberamos o Secret aqui.
|
|
45
|
+
// Sem isso, a chave chegaria como objeto/undefined e o fluxo de authorize quebraria
|
|
46
|
+
// (keygrip: "key argument must be of type string ...").
|
|
47
|
+
const rawAppKey = this.app.config.get('app.appKey');
|
|
48
|
+
const appKey = rawAppKey && typeof rawAppKey.release === 'function'
|
|
49
|
+
? rawAppKey.release()
|
|
50
|
+
: rawAppKey;
|
|
51
|
+
if (!appKey || typeof appKey !== 'string') {
|
|
52
|
+
throw new RuntimeException('APP_KEY ausente: defina `export const appKey = new Secret(env.get(\'APP_KEY\'))` em config/app.ts. ' +
|
|
53
|
+
'O @dudousxd/adonis-authkit-server precisa dele para assinar os cookies do oidc-provider.');
|
|
54
|
+
}
|
|
55
|
+
const metrics = await this.app.container.make('authkit.metrics');
|
|
56
|
+
return new OidcService(config, appKey, metrics);
|
|
57
|
+
});
|
|
58
|
+
this.app.container.singleton('authkit.metrics', async () => {
|
|
59
|
+
const value = this.app.config.get('authkit');
|
|
60
|
+
const config = (await configProvider.resolve(this.app, value));
|
|
61
|
+
const { createMetricsRecorder } = await import('../src/observability/metrics_service.js');
|
|
62
|
+
return createMetricsRecorder(config?.observability ?? {}, 'authkit-server');
|
|
63
|
+
});
|
|
64
|
+
this.app.container.singleton('authkit.accountStore', async () => {
|
|
65
|
+
const value = this.app.config.get('authkit');
|
|
66
|
+
const config = (await configProvider.resolve(this.app, value));
|
|
67
|
+
if (!config?.accountStore) {
|
|
68
|
+
throw new RuntimeException('accountStore não configurado em "config/authkit.ts". Use defineConfig de @dudousxd/adonis-authkit-server.');
|
|
69
|
+
}
|
|
70
|
+
return config.accountStore;
|
|
71
|
+
});
|
|
72
|
+
this.app.container.singleton('authkit.patStore', async () => {
|
|
73
|
+
const value = this.app.config.get('authkit');
|
|
74
|
+
const config = (await configProvider.resolve(this.app, value));
|
|
75
|
+
if (!config?.patStore) {
|
|
76
|
+
throw new RuntimeException('patStore não configurado em "config/authkit.ts" — necessário para fluxos de PAT.');
|
|
77
|
+
}
|
|
78
|
+
return config.patStore;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/** DTO público da conta — o que o provider e os controllers enxergam. Nunca um model Lucid. */
|
|
2
|
+
export interface AuthAccount {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
globalRoles?: string[];
|
|
6
|
+
name?: string;
|
|
7
|
+
avatarUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CreateAccountInput {
|
|
10
|
+
email: string;
|
|
11
|
+
password: string;
|
|
12
|
+
fullName?: string | null;
|
|
13
|
+
globalRoles?: string[];
|
|
14
|
+
/** social/Google entra como true (provider já verificou o email). Default: false. */
|
|
15
|
+
emailVerified?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Dados para ligar uma identidade de provider a uma conta. */
|
|
18
|
+
export interface LinkProviderIdentityInput {
|
|
19
|
+
accountId: string;
|
|
20
|
+
provider: string;
|
|
21
|
+
providerUserId: string;
|
|
22
|
+
email?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Parâmetros de listagem paginada de contas (console admin). */
|
|
25
|
+
export interface ListAccountsParams {
|
|
26
|
+
/** Filtro por e-mail (substring, case-insensitive). */
|
|
27
|
+
search?: string;
|
|
28
|
+
/** Página (1-based). Default: 1. */
|
|
29
|
+
page?: number;
|
|
30
|
+
/** Itens por página. Default: 20. */
|
|
31
|
+
limit?: number;
|
|
32
|
+
}
|
|
33
|
+
/** Página de resultados + total absoluto (para paginação na UI). */
|
|
34
|
+
export interface Paginated<T> {
|
|
35
|
+
data: T[];
|
|
36
|
+
total: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resumo de uma passkey (credencial WebAuthn) para exibição na UI de gerência.
|
|
40
|
+
* Nunca expõe a chave pública nem o counter.
|
|
41
|
+
*/
|
|
42
|
+
export interface PasskeySummary {
|
|
43
|
+
/** Credential id (base64url). */
|
|
44
|
+
id: string;
|
|
45
|
+
/** Rótulo legível opcional (ex.: nome do dispositivo). */
|
|
46
|
+
label?: string;
|
|
47
|
+
/** ISO timestamp de criação. */
|
|
48
|
+
createdAt: string;
|
|
49
|
+
}
|
|
50
|
+
export interface AccountStore {
|
|
51
|
+
findById(id: string): Promise<AuthAccount | null>;
|
|
52
|
+
verifyCredentials(email: string, password: string): Promise<AuthAccount | null>;
|
|
53
|
+
findByEmail(email: string): Promise<AuthAccount | null>;
|
|
54
|
+
create(input: CreateAccountInput): Promise<AuthAccount>;
|
|
55
|
+
/** Acha a conta ligada a uma identidade de provider; null se desconhecida. */
|
|
56
|
+
findByProviderIdentity(provider: string, providerUserId: string): Promise<AuthAccount | null>;
|
|
57
|
+
/** Liga (upsert idempotente na chave única) uma identidade de provider a uma conta. */
|
|
58
|
+
linkProviderIdentity(data: LinkProviderIdentityInput): Promise<void>;
|
|
59
|
+
issuePasswordResetToken(email: string): Promise<{
|
|
60
|
+
token: string;
|
|
61
|
+
account: AuthAccount;
|
|
62
|
+
} | null>;
|
|
63
|
+
consumePasswordResetToken(token: string, newPassword: string): Promise<boolean>;
|
|
64
|
+
issueEmailVerificationToken(email: string): Promise<{
|
|
65
|
+
token: string;
|
|
66
|
+
account: AuthAccount;
|
|
67
|
+
} | null>;
|
|
68
|
+
consumeEmailVerificationToken(token: string): Promise<boolean>;
|
|
69
|
+
/** Lista contas paginadas, opcionalmente filtrando por e-mail. */
|
|
70
|
+
listAccounts(params: ListAccountsParams): Promise<Paginated<AuthAccount>>;
|
|
71
|
+
/** Substitui as roles globais de uma conta. */
|
|
72
|
+
setGlobalRoles(accountId: string, roles: string[]): Promise<void>;
|
|
73
|
+
/** Estado do MFA da conta (se o desafio TOTP deve ser exigido no login). */
|
|
74
|
+
getMfaState?(accountId: string): Promise<{
|
|
75
|
+
enabled: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
/**
|
|
78
|
+
* Inicia o enrollment TOTP: gera um segredo PENDENTE (mfaEnabledAt continua
|
|
79
|
+
* null) e devolve o segredo + otpauth URI (keyuri). Não ativa o MFA ainda.
|
|
80
|
+
*/
|
|
81
|
+
startTotpEnrollment?(accountId: string): Promise<{
|
|
82
|
+
secret: string;
|
|
83
|
+
otpauthUri: string;
|
|
84
|
+
} | null>;
|
|
85
|
+
/**
|
|
86
|
+
* Confirma o enrollment: verifica o código contra o segredo pendente; em caso
|
|
87
|
+
* de sucesso ativa o MFA, gera N recovery codes e devolve os códigos em claro
|
|
88
|
+
* (uma única vez).
|
|
89
|
+
*/
|
|
90
|
+
confirmTotpEnrollment?(accountId: string, code: string): Promise<{
|
|
91
|
+
ok: boolean;
|
|
92
|
+
recoveryCodes?: string[];
|
|
93
|
+
}>;
|
|
94
|
+
/** Verifica um código TOTP contra o segredo ativo. */
|
|
95
|
+
verifyTotp?(accountId: string, code: string): Promise<boolean>;
|
|
96
|
+
/** Consome (single-use) um recovery code; true se casou e foi removido. */
|
|
97
|
+
consumeRecoveryCode?(accountId: string, code: string): Promise<boolean>;
|
|
98
|
+
/** Desliga o MFA: limpa segredo + mfaEnabledAt + recovery codes. */
|
|
99
|
+
disableMfa?(accountId: string): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Inicia o registro de uma passkey: gera as opções de criação
|
|
102
|
+
* (`generateRegistrationOptions`) escopadas à conta (e excluindo credenciais já
|
|
103
|
+
* registradas). Devolve as opções JSON (o controller serializa pro browser) e o
|
|
104
|
+
* `challenge` (base64url) para guardar na sessão. null = conta inexistente.
|
|
105
|
+
*/
|
|
106
|
+
generatePasskeyRegistrationOptions?(accountId: string): Promise<{
|
|
107
|
+
options: Record<string, unknown>;
|
|
108
|
+
challenge: string;
|
|
109
|
+
} | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Finaliza o registro: verifica a resposta do browser
|
|
112
|
+
* (`verifyRegistrationResponse`) contra o `expectedChallenge` guardado. Em caso
|
|
113
|
+
* de sucesso persiste a credencial (id, publicKey, counter, transports) e
|
|
114
|
+
* habilita o MFA. Retorna true se registrou.
|
|
115
|
+
*/
|
|
116
|
+
verifyPasskeyRegistration?(accountId: string, response: unknown, expectedChallenge: string): Promise<boolean>;
|
|
117
|
+
/**
|
|
118
|
+
* Inicia a autenticação por passkey no login: gera as opções
|
|
119
|
+
* (`generateAuthenticationOptions`) restritas às credenciais da conta. Devolve
|
|
120
|
+
* as opções JSON + o `challenge` para guardar na sessão. null = conta sem passkeys.
|
|
121
|
+
*/
|
|
122
|
+
generatePasskeyAuthenticationOptions?(accountId: string): Promise<{
|
|
123
|
+
options: Record<string, unknown>;
|
|
124
|
+
challenge: string;
|
|
125
|
+
} | null>;
|
|
126
|
+
/**
|
|
127
|
+
* Verifica a resposta de autenticação por passkey
|
|
128
|
+
* (`verifyAuthenticationResponse`) contra o `expectedChallenge` guardado. Em
|
|
129
|
+
* caso de sucesso atualiza o signature counter armazenado. Retorna true se válido.
|
|
130
|
+
*/
|
|
131
|
+
verifyPasskeyAuthentication?(accountId: string, response: unknown, expectedChallenge: string): Promise<boolean>;
|
|
132
|
+
/** Lista as passkeys da conta (sem expor chave pública / counter). */
|
|
133
|
+
listPasskeys?(accountId: string): Promise<PasskeySummary[]>;
|
|
134
|
+
/** Remove uma passkey (por credential id) da conta. */
|
|
135
|
+
removePasskey?(accountId: string, credentialId: string): Promise<void>;
|
|
136
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { generateAuthenticationOptions, generateRegistrationOptions, verifyAuthenticationResponse, verifyRegistrationResponse } from '@simplewebauthn/server';
|
|
2
|
+
import type { AccountStore } from './account_store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Encripta/decripta um valor (ex.: o segredo TOTP) em repouso. Mantém a lib
|
|
5
|
+
* desacoplada do serviço de encryption do app — qualquer implementação que
|
|
6
|
+
* faça round-trip serve (em prod, normalmente o `@adonisjs/core/services/encryption`).
|
|
7
|
+
* `decrypt` retorna `null` se o valor foi adulterado/é inválido.
|
|
8
|
+
*/
|
|
9
|
+
export interface AccountSecretEncrypter {
|
|
10
|
+
encrypt(value: string): string;
|
|
11
|
+
decrypt(value: string): string | null;
|
|
12
|
+
}
|
|
13
|
+
/** Opções do {@link lucidAccountStore}. */
|
|
14
|
+
export interface LucidAccountStoreOptions {
|
|
15
|
+
/** Label de issuer mostrado no app autenticador (keyuri). Default: 'AuthKit'. */
|
|
16
|
+
mfaIssuer?: string;
|
|
17
|
+
/** Quantidade de recovery codes gerados no enrollment. Default: 8. */
|
|
18
|
+
recoveryCodeCount?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Quando fornecido, o segredo TOTP é encriptado antes de persistir e
|
|
21
|
+
* decriptado na leitura. Ausente (ex.: testes) → segredo em claro.
|
|
22
|
+
*/
|
|
23
|
+
encrypter?: AccountSecretEncrypter;
|
|
24
|
+
/**
|
|
25
|
+
* Model Lucid das identidades de provider (composto de `withProviderIdentity()`),
|
|
26
|
+
* usado por `findByProviderIdentity`/`linkProviderIdentity` (account linking
|
|
27
|
+
* social). Ausente → esses dois métodos lançam (hosts email-only continuam
|
|
28
|
+
* funcionando até optarem por habilitar).
|
|
29
|
+
*/
|
|
30
|
+
providerIdentityModel?: any;
|
|
31
|
+
/**
|
|
32
|
+
* Model Lucid das credenciais WebAuthn / passkeys (composto de
|
|
33
|
+
* `withWebauthnCredential()`), usado pelos métodos `*Passkey*`. Ausente → esses
|
|
34
|
+
* métodos viram `undefined` na interface (hosts sem passkeys não mudam de
|
|
35
|
+
* comportamento; a UI esconde a seção de passkeys).
|
|
36
|
+
*/
|
|
37
|
+
webauthnCredentialModel?: any;
|
|
38
|
+
/**
|
|
39
|
+
* Parâmetros do Relying Party (RP) usados nas cerimônias WebAuthn. Resolvidos a
|
|
40
|
+
* partir do `issuer` no `define_config` quando omitidos. Necessários sempre que
|
|
41
|
+
* `webauthnCredentialModel` é fornecido.
|
|
42
|
+
*/
|
|
43
|
+
webauthn?: {
|
|
44
|
+
/** Nome do RP mostrado pelo authenticator. Default: `mfaIssuer`. */
|
|
45
|
+
rpName: string;
|
|
46
|
+
/** RP ID — normalmente o hostname (sem porta) do issuer. */
|
|
47
|
+
rpId: string;
|
|
48
|
+
/** Origin(s) esperada(s) na verificação (scheme://host[:port]). */
|
|
49
|
+
origin: string | string[];
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Seam de injeção das cerimônias WebAuthn (generate/verify). Default: as funções
|
|
53
|
+
* reais do `@simplewebauthn/server`. Existe para testes (mockar a verificação SEM
|
|
54
|
+
* um authenticator real) — produção não precisa fornecer.
|
|
55
|
+
*/
|
|
56
|
+
webauthnCeremonies?: Partial<WebauthnCeremonies>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Funções das cerimônias WebAuthn. Espelham a assinatura do `@simplewebauthn/server`
|
|
60
|
+
* (subconjunto usado). Injetáveis via {@link LucidAccountStoreOptions.webauthnCeremonies}
|
|
61
|
+
* para testes.
|
|
62
|
+
*/
|
|
63
|
+
export interface WebauthnCeremonies {
|
|
64
|
+
generateRegistrationOptions: typeof generateRegistrationOptions;
|
|
65
|
+
verifyRegistrationResponse: typeof verifyRegistrationResponse;
|
|
66
|
+
generateAuthenticationOptions: typeof generateAuthenticationOptions;
|
|
67
|
+
verifyAuthenticationResponse: typeof verifyAuthenticationResponse;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Implementação default do {@link AccountStore} sobre um model Lucid composto
|
|
71
|
+
* de `withAuthUser()` + `withCredentials()` (+ opcionalmente `withMfa()`). O
|
|
72
|
+
* model carrega `connection`/`table` (app-específico) e, por convenção, uma
|
|
73
|
+
* coluna `fullName` (mapeada de `name`).
|
|
74
|
+
*/
|
|
75
|
+
export declare function lucidAccountStore(Model: any, options?: LucidAccountStoreOptions): AccountStore;
|