A plataforma
12 · Identidade e acesso
Toda aplicação com área restrita é autenticada no Keycloak do toolbox e autoriza
por permissões que ela mesma declara. Pessoas recebem acesso por perfis, atribuídos
por grupos. Outras aplicações recebem acesso por contas de serviço. Tudo isso
é declarado no repositório e documentado por aplicação.
O modelo em um diagrama
| Conceito | No Keycloak | Quem cria | Quem atribui |
|---|---|---|---|
| Realm | No Keycloak: realm | Quem cria: toolbox (ADR lá) | Quem atribui: — |
| Client da aplicação | No Keycloak: client confidencial | Quem cria: eng/auth/provision.sh da stack | Quem atribui: — |
Permissão <recurso>:<ação> | No Keycloak: client role do client da aplicação | Quem cria: provision.sh | Quem atribui: só via perfil |
Perfil perfil:<nome> | No Keycloak: client role composto | Quem cria: provision.sh | Quem atribui: via grupo |
Grupo <produto>-<perfil-plural> | No Keycloak: grupo do realm | Quem cria: provision.sh | Quem atribui: administrador do realm põe as pessoas |
| Perfil padrão | No Keycloak: default-roles-<realm> inclui o perfil | Quem cria: provision.sh | Quem atribui: automático, todo usuário do realm |
| Conta de serviço | No Keycloak: service account de outro client | Quem cria: provision.sh da aplicação consumidora | Quem atribui: recebe permissões do client provedor |
Aplicação pública
Nem toda aplicação tem usuários: um site, uma landing, uma página de documentação podem ser públicos, sem login. Isso é uma decisão declarada, não uma omissão:
| Tipo de aplicação | Identidade | O que se declara |
|---|---|---|
| Restrita | Identidade: client no Keycloak, <app>:acessar e pelo menos um perfil desde a fundação | O que se declara: docs/acesso/<app>.md completo |
| Pública | Identidade: nenhuma; sem client, sem sessão | O que se declara: na ficha e em docs/acesso/<app>.md: "pública", o que ela expõe e o que nunca pode expor (dado de usuário, rota de administração) |
| Mista | Identidade: client e permissões só para a parte restrita | O que se declara: as rotas públicas listadas uma a uma; o resto exige login |
Toda aplicação, pública ou não, cumpre o contrato de observabilidade e tem /up.
Regras
- Realm por população, não por aplicação. Colaboradores da Hibex em
hibex-team; clientes externos em realm de produto (ex.:hibex-enterprise). Colaborador e cliente nunca no mesmo realm (toolbox ADR-0008). Criar realm é decisão dotoolbox; - Um client por aplicação, confidencial, Authorization Code com PKCE S256,
directAccessGrantsEnabled=false, redirect e post-logout redirect exatos (produção +localhost); - O código confere permissões, nunca perfis. O perfil é organização de pessoas; o código não muda quando um perfil ganha ou perde uma permissão;
- Ninguém recebe papel direto no usuário. Perfil vai para grupo (toolbox ADR-0034); quando toda a população tem o mesmo acesso, o perfil vai para os default roles do realm — e isso também é declarado;
- A aplicação lê
resource_access.<client-id>.rolesdo access token, sem chamada extra por requisição; - Sem senha nem sessão local. O Keycloak autentica: a aplicação não tem login, senha nem cadastro de usuário próprios. Ela pode, sim, manter uma sessão (um cookie), mas essa sessão guarda só os tokens do Keycloak e expira com eles; nunca é uma conta da aplicação;
- Sem acesso de negado mudo. Autenticado sem permissão vê uma página que diz qual perfil (e qual grupo) dá acesso;
- Configuração como código.
eng/auth/provision.sh <realm>é idempotente: cria o que falta, atualiza o que existe, reexecutar não muda nada; nunca regenera segredo de client (só lê e imprime para guardar no Bitwarden); - IdP externo (Google) por script, com credenciais do ambiente — nunca no export do realm versionado; um OAuth client do Google por realm;
- Realms de desenvolvimento versionados em
eng/auth/dev-realms/, gerados a partir doprovision.sh, com um usuário de exemplo por perfil (senha = primeiro nome) e um usuário sem nenhum perfil, e segredos de client óbvios (dev-secret-<client>).
Ambientes e realms
Uma stack tem dois ambientes: o local, com o Keycloak descartável do Compose e os realms de
desenvolvimento da regra 10, e a produção, com os realms reais. O toolbox já criou o
hibex-enterprise-dev (a ADR-0039 de lá), um realm na instância real para ambientes
implantados de desenvolvimento do produto Hibex Enterprise. Por enquanto, nenhuma stack o usa:
um ambiente implantado de desenvolvimento pede ainda um realm para os colaboradores (não há um
hibex-team-dev, e o hibex-team nunca serve de bancada de testes), um host, um valor de
deployment.environment e um projeto no Bitwarden. A arquitetura o define quando a primeira
stack precisar testar implantada. Até lá, o provision.sh já recebe o realm como argumento
(regra 8): é o que permite, depois, rodá-lo em outro realm sem mudar o script.
Login, do clique ao acesso
Permissões e perfis: como desenhar
(Exemplo ilustrativo, no produto fictício de 03. O modelo pede o desenho fino desde o início, mesmo que a primeira versão tenha um perfil com todas as permissões — assim um perfil novo não exige mexer no código.)
Orientações:
- Permissão nomeia um recurso e uma ação do ponto de vista do negócio:
carteira:conceder, nãoPOST /carteiras. Ações típicas:ler,criar,editar,excluir, mais verbos do domínio (publicar,atender,aprovar); - Perfil nomeia um papel de trabalho reconhecível pelas pessoas: gestor, analista, financeiro, cliente;
- O mínimo de toda aplicação com usuários: uma permissão de entrada
(
<app>:acessar) e um perfil; - Permissões de API (para outras aplicações) têm o prefixo
api:— ex.:api:chamado:ler—, para nunca se confundirem com permissões de tela.
O documento de acesso de cada aplicação (docs/acesso/<app>.md)
Cada aplicação tem o seu. É o documento que o administrador do realm, o mantenedor e uma equipe de outra aplicação leem para saber "quem pode o quê". Estrutura obrigatória:
# Acesso — <app>
## Resumo
| Realm | Client | Endereço | Perfil padrão |
|---|---|---|---|
## Permissões
| Permissão | O que permite | Telas / rotas | Desde (change) |
|---|---|---|---|
| chamado:ler | ver a lista e o detalhe dos chamados | /chamados, /chamados/{id} | identidade |
## Perfis
| Perfil | Para quem | Grupo | Permissões |
|---|---|---|---|
| perfil:gestor | quem conduz os atendimentos | atendimento-gestores | chamado:ler, chamado:atender, … |
## Matriz perfil × permissão
| Permissão \ Perfil | gestor | analista | financeiro |
|---|---|---|---|
| chamado:ler | ✓ | ✓ | |
## Como dar acesso a uma pessoa
1. No realm <realm>, Usuários → a pessoa → Grupos → entrar em <grupo>;
2. A pessoa sai e entra de novo (o token novo traz o perfil).
## Como outra aplicação obtém acesso à API desta
(permissões `api:*`, audiência, exemplo de token — ver seção do guia)
## Usuários de desenvolvimento
| Usuário / senha | Perfil | Serve para |
|---|---|---|
| ana.souza / ana | gestor | caminho feliz da gestão |
| bruno.dias / bruno | nenhum | ver o 403 explicativo |
## Histórico
| Data | Change | O que mudou no acesso |A seção Matriz é verificada de ponta a ponta pelo agrupamento E2E identidade: um
caso por perfil confere o que ele vê e o que não vê.
Acesso entre aplicações
Quando uma aplicação B precisa chamar a API da aplicação A (de outra stack ou da
mesma), o padrão é client credentials com a conta de serviço de B recebendo
permissões api:* do client de A.
Quem faz o quê:
| Passo | Repositório |
|---|---|
Declarar a permissão api:chamado:ler no client a | Repositório: stack de A (eng/auth/provision.sh) |
| Documentar a permissão na seção "Como outra aplicação obtém acesso" | Repositório: stack de A (docs/acesso/a.md) |
Criar o client b com conta de serviço, dar a ela api:chamado:ler de a, e o mapper de audiência | Repositório: stack de B (eng/auth/provision.sh) |
Validar o token como resource server (emissor, aud, permissão) | Repositório: stack de A (código + teste de integração) |
Regras: a aplicação provedora nunca confia num token sem aud próprio; tokens de
usuário não são repassados entre aplicações (cada chamada de serviço usa a conta de
serviço de quem chama).
eng/auth/: identidade como código
| Arquivo | Papel |
|---|---|
README.md | Papel: Tabela, por aplicação, de client, redirects, permissões, perfis, grupos, IdPs — legível sem acesso ao Keycloak |
provision.sh | Papel: Cria/atualiza client, permissões, perfis (compostos), grupos, vínculos, default roles, mappers de audiência, IdP (se houver credenciais). Imprime o segredo do client uma vez, para o Bitwarden |
dev-realms.sh | Papel: Sobe um Keycloak descartável, cria os realms, roda o provision.sh, cria os usuários de exemplo, fixa os segredos de dev e exporta |
dev-realms/*.json | Papel: Os exports, importados pelo Compose e pelos testes |
google-dev.sh + google-dev.local | Papel: IdP Google local, opcional |
Mudou acesso? A change mexe no provision.sh, roda o dev-realms.sh, confere o diff
dos JSON, atualiza docs/acesso/<app>.md e os casos do agrupamento identidade.
Em produção (guia docs/guias/identidade.md)
Roteiro que o mantenedor segue; o agente só o escreve.
Funcionalidades de identidade que se repetem
Oferecidas como guia (não obrigatórias):
| Funcionalidade | Como |
|---|---|
| Portão de primeiro acesso (preferências obrigatórias antes de usar) | Como: filtro após a autorização, preservando o deep link |
| Edição de nome pelo próprio usuário | Como: Account API do Keycloak com o token do usuário (aud: account), sem conta administrativa |
| Entrada direta no IdP a partir de uma landing | Como: kc_idp_hint num ponto de entrada público |
| Logout completo | Como: RP-initiated logout com post-logout redirect para uma página pública |
| Diretório interno de usuários | Como: registro próprio com id interno, sincronizado a cada login (nunca o sub como chave de negócio) |