O Access Management como Authorization Server local, os modos Keycloak e Autentika, e a configuração obrigatória antes de arrancar.
O workspace segue o mesmo contrato de autenticação do igrp-stack em Kubernetes. O Access Management é o Authorization Server OAuth2 local: emite os tokens, guarda as sessões e federa para um IdP a montante. As aplicações autenticam sempre nele, nunca directamente no provedor de identidade.
Browser / Next.js
|
v
Access Management (issuer, JWKS, tokens e sessões)
|
+-- Keycloak (igrp-compose.yaml)
`-- Autentika (igrp-autentika-compose.yaml)Todos os frontends usam AUTH_PROVIDER=igrp-auth e apontam o IGRP_AUTH_ISSUER ao Access Management. A escolha entre Keycloak e Autentika faz-se apenas pelas variáveis IGRP_OAUTH_EXTERNAL_IDP_* do Access Management.
Os dois modos
São mutuamente exclusivos — nunca os dois ao mesmo tempo.
| Keycloak | Autentika | |
|---|---|---|
| Ficheiros | .env, igrp-compose.yaml, process/.env_process, process/igrp-process-compose.yaml | .igrp-autentika.env, igrp-autentika-compose.yaml, process/.env_process_autentika, process/igrp-process-autentika-compose.yaml |
AUTH_PROVIDER | igrp-auth | igrp-auth |
| IdP externo | IGRP_OAUTH_EXTERNAL_IDP_* do realm Keycloak local | IGRP_OAUTH_EXTERNAL_IDP_* do issuer Autentika |
Os composes dos projetos são iguais nos dois modos — só muda o env-file que lhes passas.
O que mudou da v1 para a v2
| Área | v1 | v2 |
|---|---|---|
| Access Management | cliente/resource server do IdP | Authorization Server com IGRP_OAUTH_ISSUER, cliente seeded e service account |
| IdP externo | IGRP_KEYCLOAK_* / AUTENTIKA_* no frontend | IGRP_OAUTH_EXTERNAL_IDP_* só no Access Management |
| JWT | issuer do Keycloak/Autentika | AUTH_JWT_ISSUER = issuer público do Access Management |
| M2M | token estático (IGRP_M2M_TOKEN) | client_credentials por serviço |
| Persistência OAuth | tabelas da aplicação | tarefa -sas-schema cria oauth2_authorization* de forma idempotente |
| Base de dados do AM | POSTGRES_* | DATABASE_URL + SPRING_DATASOURCE_*, SPRING_FLYWAY_ENABLED=false, DDL update |
| Redis | SPRING_DATA_REDIS_* | REDIS_HOST / REDIS_PORT / REDIS_PASSWORD |
| Process APIs | token estático, issuer do IdP | issuer do AM, SPRING_APPLICATION_NAME = client ID, M2M client_credentials |
| Proxy | prefixo /gateway-api removido | o Nginx preserva X-Forwarded-Prefix para o AM construir URLs públicas correctas |
Não há token estático
Todo o M2M é client_credentials. As variáveis IGRP_ACCESS_M2M_SYNC_TOKEN e IGRP_M2M_TOKEN são resíduo da v1 e não são usadas por nenhum compose.
Configuração obrigatória antes de arrancar
1. O segredo do cliente seeded
ACCESS_MANAGEMENT_OAUTH_CLIENT_SECRET tem de ser o mesmo valor em .env, .igrp-autentika.env e nos dois env-files do Process. É o segredo do cliente usado pelo login OIDC de todos os frontends — se divergir, o login falha.
2. As chaves RSA
Sem IGRP_OAUTH_PUBLIC_KEY / IGRP_OAUTH_PRIVATE_KEY, o Access Management usa as chaves de desenvolvimento embutidas na imagem.
As chaves embutidas são públicas
Só aceitável localmente. Num ambiente partilhado, monta um par RSA estável e aponta estas duas variáveis a file:/.../public.pem e file:/.../private.pem.
3. O hostname
DOCKER_IP é o hostname público do issuer e dos callbacks, e tem de resolver no browser. Todo o acesso é ${DOCKER_IP}:${NGINX_HTTP_PORT} — nunca um nome ou IP de contentor.
4. O cookie de sessão
O workspace corre em HTTP simples, logo ACCESS_MANAGEMENT_SESSION_COOKIE_SECURE=false.
Um cookie Secure sobre HTTP é descartado
O browser deita-o fora, cria sessão nova a cada pedido, e o login falha com authorization_request_not_found. Passa a true assim que servires por HTTPS.
5. Os clientes OAuth
São registados automaticamente pelas tarefas da stack raiz — não há passo manual. Ver Registo de clientes OAuth.
O defeito do primeiro arranque
Numa base de dados nova, o Access Management arranca a reportar sucesso mas fica funcionalmente incompleto. É reproduzível a 100% e vale a pena perceber, porque o sintoma aparece longe da causa.
O que acontece
O AuthorizationSyncService tenta registar as suas próprias 43 permissões e falha com 404 IGRP_AUTH_RESOURCE_NOT_FOUND_BY_NAME, porque o resource igrp-access-management de que precisa ainda não existe — só é criado cerca de 3,6 segundos mais tarde, pelo DefaultOAuthClientBootstrap.
O erro é registado como ERROR mas engolido: o boot continua e o serviço reporta Started ... in 29.929 seconds. Em consequência, o DefaultServiceAccountBootstrap não encontra nenhuma das 12 permissões que tem de conceder, e concede zero.
Permission 'igrp.client.list' not found in t_permission — skipping grant. Will retry on next boot. (×12)
granted=0, alreadyPresent=0, missingPermissionRow=12O sintoma
Um serviço aparentemente saudável — /actuator/health → UP — cujo service account seeded devolve 403 em GET /api/clients. Por arrasto, nenhum backend ou frontend consegue ser provisionado com credenciais M2M, e o utilizador vê apenas a página de erro do nginx.
Como o workspace o contorna
A tarefa -ready (wait-for-catalog.sh) espera pelo health do Access Management, deteta este estado e reinicia o serviço uma vez, pelo socket do Docker. No segundo boot o resource já existe, o catálogo é semeado e o service account fica com as 12 permissões (granted=12, missingPermissionRow=0). Um docker compose up -d puro basta.
Montar /var/run/docker.sock dá controlo do daemon
Na prática, root na máquina. É deliberado para desenvolvimento local e nunca aceitável em ambiente partilhado ou em produção. Aí põe ACCESS_MANAGEMENT_READY_AUTO_RESTART=false, remove o mount e faz o restart de fora.
Porque é que a prontidão é externa
A imagem do Access Management é distroless: o ENTRYPOINT é java -jar /app/app.jar, sem shell nem curl. Um command: seria entregue à JVM como argumentos e nunca correria, e um healthcheck CMD-SHELL falha sempre com stat /bin/sh: no such file or directory. Daí a tarefa externa.
Keycloak já existente
O import de realm só se aplica quando o realm ainda não existe. Em volumes já inicializados, acrescenta à mão ao cliente access-management o redirect URI da federação:
http://<DOCKER_IP>:<PORTA>/gateway-api/<ws>-access-management/login/oauth2/code/external-idpEvita apagar volumes para forçar o reimport
Actualizar pelo Admin Console preserva os utilizadores.
Verificação
curl http://demoteste-igrp:2575/gateway-api/demoteste-access-management/.well-known/openid-configuration
curl http://demoteste-igrp:2575/api/auth/providersO segundo endpoint deve expor igrp-auth — não keycloak nem autentika.
Nos backends, SPRING_APPLICATION_NAME tem de ser exactamente o respectivo client ID, senão o sync de permissões falha com recurso não encontrado. Ver Registo de clientes OAuth.
Limitações conhecidas
| Limitação | Detalhe |
|---|---|
Login directo numa UI sem sessão prévia dá 401 no /oauth2/authorize | É defeito da aplicação Access Management, não do Compose. Até sair imagem corrigida, valida pelo caminho App Center → AM → IdP |
GET /api/applications devolve 403 ao service account seeded | Falta-lhe as permissões igrp.application.*. As aplicações estão registadas — confirmável em t_application; é só a leitura pela API que falha |
O discovery anuncia scopes_supported: ["openid"] | Apesar de o cliente seeded ter também email e profile |
As variáveis NEXT_PUBLIC_* são embutidas no next build | Uma imagem construída sem os valores locais precisa de rebuild com esses build args |
O .igrpstudio/workspace.json não modela o schema SAS, a federação v2 nem os clientes OAuth | Os ficheiros Compose são a fonte operacional |
Última atualização:
