molde do realm: papel atm_responsavel e mapper acompanhante_id (app dos pais); 2FA TOTP obrigatorio para atm_admin (browser-2fa-dono)
This commit is contained in:
@@ -5,6 +5,14 @@ DERIVADO de `tenants/plataforma/realm/athleticmap-realm.json`, que e o realm
|
||||
que existe hoje. Os nove papeis e o cliente `spa` sao os de la — NAO inventei
|
||||
nenhum, e um papel a mais aqui seria um papel que nenhum codigo verifica.
|
||||
|
||||
06/10/2026 — DECIMO papel: `atm_responsavel` (responsavel legal: app dos pais
|
||||
e o portal). Verificado por codigo: o cadastro o da ao marcar o acompanhante
|
||||
como responsavel (AcessoAoAppServico), o SPA leva quem so o tem ao /portal, e
|
||||
a TravaDaEquipe o deixa FORA da leitura da equipe. Junto, o mapper
|
||||
`acompanhante_id` (atributo -> claim) nos clients `spa` e `app`, como o
|
||||
`funcionario_id`. Realm que ja existe nao reimporta: rodar
|
||||
`scripts/papel_responsavel_nos_realms.py --check` / `--aplicar`.
|
||||
|
||||
── OS MARCADORES ───────────────────────────────────────────────────────────
|
||||
|
||||
{{REALM}} `athleticmap-<N>` — decidido em 2026-09-19
|
||||
@@ -76,3 +84,17 @@ pelos runtimes.
|
||||
Nao da para resolver so no `KC_HOSTNAME` porque ele e um so, e a plataforma
|
||||
depende do valor antigo — os servicos dela estao configurados com
|
||||
`auth-plataforma`. Dai o `frontendUrl` por realm, que e exatamente para isto.
|
||||
|
||||
── DUPLO FATOR DO DONO (07/10/2026) ────────────────────────────────────────
|
||||
|
||||
`browserFlow: browser-2fa-dono` e os quatro `authenticationFlows`: copia do
|
||||
`browser` de fabrica do 26.7.5 com OTP OBRIGATORIO para `atm_admin` (quem nao
|
||||
tem configura no primeiro login) e passkey dispensando o codigo. Politica OTP
|
||||
TOTP/SHA1/6 digitos/30 s (Google e Microsoft Authenticator). Os outros fluxos
|
||||
(`direct grant`, `clients`...) o Keycloak cria sozinho na importacao — provado
|
||||
num 26.7.5 descartavel. Realms que ja existem: `scripts/dois_fatores_nos_realms.py`
|
||||
(le ESTE arquivo). Recuperacao e saida de emergencia: docs/dois-fatores-do-dono.md.
|
||||
|
||||
ATENCAO ao testar este molde num Keycloak local: o `frontendUrl` aponta para
|
||||
`https://auth.athleticmap.com` — o formulario de login POSTA EM PRODUCAO. Zere
|
||||
`attributes.frontendUrl` no realm de teste.
|
||||
|
||||
@@ -16,6 +16,197 @@
|
||||
"webAuthnPolicyPasswordlessPasskeysEnabled": true,
|
||||
"webAuthnPolicyPasswordlessUserVerificationRequirement": "required",
|
||||
"webAuthnPolicyPasswordlessRpEntityName": "Athletic Map",
|
||||
"otpPolicyType": "totp",
|
||||
"otpPolicyAlgorithm": "HmacSHA1",
|
||||
"otpPolicyDigits": 6,
|
||||
"otpPolicyPeriod": 30,
|
||||
"otpPolicyLookAheadWindow": 1,
|
||||
"otpPolicyCodeReusable": false,
|
||||
"browserFlow": "browser-2fa-dono",
|
||||
"authenticationFlows": [
|
||||
{
|
||||
"alias": "browser-2fa-dono",
|
||||
"description": "Copia do browser padrao (26.7.5) com OTP obrigatorio para quem tem atm_admin",
|
||||
"providerId": "basic-flow",
|
||||
"topLevel": true,
|
||||
"builtIn": false,
|
||||
"authenticationExecutions": [
|
||||
{
|
||||
"requirement": "ALTERNATIVE",
|
||||
"priority": 10,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "auth-cookie"
|
||||
},
|
||||
{
|
||||
"requirement": "DISABLED",
|
||||
"priority": 20,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "auth-spnego"
|
||||
},
|
||||
{
|
||||
"requirement": "ALTERNATIVE",
|
||||
"priority": 25,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "identity-provider-redirector"
|
||||
},
|
||||
{
|
||||
"requirement": "ALTERNATIVE",
|
||||
"priority": 30,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": true,
|
||||
"flowAlias": "browser-2fa-dono-forms"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alias": "browser-2fa-dono-forms",
|
||||
"description": "Usuario e senha (ou passkey), e o segundo fator",
|
||||
"providerId": "basic-flow",
|
||||
"topLevel": false,
|
||||
"builtIn": false,
|
||||
"authenticationExecutions": [
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 10,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "auth-username-password-form"
|
||||
},
|
||||
{
|
||||
"requirement": "CONDITIONAL",
|
||||
"priority": 20,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": true,
|
||||
"flowAlias": "browser-2fa-dono-otp-obrigatorio"
|
||||
},
|
||||
{
|
||||
"requirement": "CONDITIONAL",
|
||||
"priority": 30,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": true,
|
||||
"flowAlias": "browser-2fa-dono-2fa-opcional"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alias": "browser-2fa-dono-otp-obrigatorio",
|
||||
"description": "atm_admin: OTP obrigatorio (configura no 1o login); passkey dispensa",
|
||||
"providerId": "basic-flow",
|
||||
"topLevel": false,
|
||||
"builtIn": false,
|
||||
"authenticationExecutions": [
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 10,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "conditional-user-role",
|
||||
"authenticatorConfig": "2fa-dono-papel-atm-admin"
|
||||
},
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 20,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "conditional-credential",
|
||||
"authenticatorConfig": "2fa-dono-sem-passkey"
|
||||
},
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 30,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "auth-otp-form"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"alias": "browser-2fa-dono-2fa-opcional",
|
||||
"description": "Os demais: como o padrao (2FA so de quem configurou)",
|
||||
"providerId": "basic-flow",
|
||||
"topLevel": false,
|
||||
"builtIn": false,
|
||||
"authenticationExecutions": [
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 10,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "conditional-user-configured"
|
||||
},
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 20,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "conditional-credential",
|
||||
"authenticatorConfig": "2fa-opcional-sem-passkey"
|
||||
},
|
||||
{
|
||||
"requirement": "REQUIRED",
|
||||
"priority": 30,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "conditional-user-role",
|
||||
"authenticatorConfig": "2fa-opcional-nao-dono"
|
||||
},
|
||||
{
|
||||
"requirement": "ALTERNATIVE",
|
||||
"priority": 40,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "auth-otp-form"
|
||||
},
|
||||
{
|
||||
"requirement": "DISABLED",
|
||||
"priority": 50,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "webauthn-authenticator"
|
||||
},
|
||||
{
|
||||
"requirement": "DISABLED",
|
||||
"priority": 60,
|
||||
"userSetupAllowed": false,
|
||||
"authenticatorFlow": false,
|
||||
"authenticator": "auth-recovery-authn-code-form"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"authenticatorConfig": [
|
||||
{
|
||||
"alias": "2fa-dono-papel-atm-admin",
|
||||
"config": {
|
||||
"condUserRole": "atm_admin",
|
||||
"negate": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"alias": "2fa-dono-sem-passkey",
|
||||
"config": {
|
||||
"credentials": "webauthn-passwordless",
|
||||
"included": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"alias": "2fa-opcional-sem-passkey",
|
||||
"config": {
|
||||
"credentials": "webauthn-passwordless",
|
||||
"included": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
"alias": "2fa-opcional-nao-dono",
|
||||
"config": {
|
||||
"condUserRole": "atm_admin",
|
||||
"negate": "true"
|
||||
}
|
||||
}
|
||||
],
|
||||
"roles": {
|
||||
"realm": [
|
||||
{
|
||||
@@ -44,6 +235,10 @@
|
||||
},
|
||||
{
|
||||
"name": "atm_financeiro-leitura"
|
||||
},
|
||||
{
|
||||
"name": "atm_responsavel",
|
||||
"description": "Responsavel legal (pai, mae ou outro): app dos pais e o portal web. Dado pelo cadastro ao marcar o acompanhante como responsavel (06/10/2026)."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -80,6 +275,20 @@
|
||||
"access.token.claim": "true",
|
||||
"userinfo.token.claim": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "acompanhante_id",
|
||||
"protocol": "openid-connect",
|
||||
"protocolMapper": "oidc-usermodel-attribute-mapper",
|
||||
"consentRequired": false,
|
||||
"config": {
|
||||
"user.attribute": "acompanhante_id",
|
||||
"claim.name": "acompanhante_id",
|
||||
"jsonType.label": "String",
|
||||
"id.token.claim": "true",
|
||||
"access.token.claim": "true",
|
||||
"userinfo.token.claim": "true"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -123,6 +332,20 @@
|
||||
"access.token.claim": "true",
|
||||
"userinfo.token.claim": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "acompanhante_id",
|
||||
"protocol": "openid-connect",
|
||||
"protocolMapper": "oidc-usermodel-attribute-mapper",
|
||||
"consentRequired": false,
|
||||
"config": {
|
||||
"user.attribute": "acompanhante_id",
|
||||
"claim.name": "acompanhante_id",
|
||||
"jsonType.label": "String",
|
||||
"id.token.claim": "true",
|
||||
"access.token.claim": "true",
|
||||
"userinfo.token.claim": "true"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user