Gateway — access token Microsoft Entra (Modo B)

Guia para DevOps e clientes que exigem Access Token Entra (aud = api://{app-id}) no API Gateway, em vez do JWT ECOSIF (Modo A).

Código tarefa: AUTH-09 · P7-06
Público: administradores Entra ID, DevOps, arquitetos de integração
Pré-requisitos: App Registration com API exposta (ver runbook Azure Entra §3)


Quando usar

Cenário Modo
Gateway interno (Traefik) com secret compartilhado AECOSIF_JWT + gateway_jwt_ecosif.md
Cliente com Azure API Management, ALB ou WAF que só aceita token Microsoft BAZURE_ENTERPRISE_GATEWAY

Regra: ECOSIF_API_TOKEN_MODE e ECOSIF_AUTH_PROVIDER devem estar alinhados em Angular, backends e gateway.


Visão geral do fluxo

Login (uma vez)
  Angular/MSAL popup → id_token
  → POST /api/auth/external-login { provider: "AZURE_ENTERPRISE", token: "<id_token>" }
  → ecosif-auth valida id_token, provisiona gr_user + identity_provider_link
  → resposta { accessToken: <JWT_ECOSIF> }  ← sessão/guard Angular apenas

APIs de negócio (cada requisição)
  Angular acquireTokenSilent → access_token (aud = api://{client-id})
  → Authorization: Bearer <access_token>
  → API Gateway valida JWKS Entra (aud, iss, exp)
  → microsserviço valida o mesmo token (OAuth2 Resource Server)
  → resolve usuário: claim oid/sub → identity_provider_link → gr_user

Dois tokens Microsoft coexistem:

Token Onde aud típico Validador
ID Token POST /api/auth/external-login Client ID (SPA) ecosif-auth (JWKS)
Access Token Authorization em /ecosif-* api://{client-id} Gateway + backends

O JWT ECOSIF não trafega nas APIs de negócio no Modo B.


Variáveis de ambiente

Stack completa (compose / ECS)

# Modo B — obrigatório alinhar em todos os serviços + Angular
ECOSIF_API_TOKEN_MODE=AZURE_ENTERPRISE_GATEWAY
ECOSIF_AUTH_PROVIDER=AZURE_ENTERPRISE

# Gateway — documentação/ops (≤32 chars)
ECOSIF_GWVAL_JWT_ECOSIF=false
ECOSIF_GWVAL_ACCESSTOKEN_MS=true

# Entra — mesmos valores do runbook Azure
ECOSIF_AZURE_CLIENT_ID=<application-client-id>
ECOSIF_AZURE_TENANT_ID=<directory-tenant-id>
ECOSIF_AZURE_AUTHORITY=https://login.microsoftonline.com/<tenant-id>
ECOSIF_AZURE_SCOPES=openid,profile,email,api://<client-id>/access_as_user
ECOSIF_AZURE_API_AUDIENCE=api://<client-id>

# Angular
ECOSIF_ENABLE_AZURE_AUTH=true
ECOSIF_ENABLE_LOCAL_AUTH=false   # típico em SSO obrigatório

Backends Java (application.ymlecosif.security.*)

Propriedade Variável Descrição
ecosif.security.api-token-mode ECOSIF_API_TOKEN_MODE AZURE_ENTERPRISE_GATEWAY
ecosif.security.auth-provider ECOSIF_AUTH_PROVIDER AZURE_ENTERPRISE
ecosif.security.azure.tenant-id ECOSIF_AZURE_TENANT_ID Tenant para JWKS/issuer
ecosif.security.azure.api-audience ECOSIF_AZURE_API_AUDIENCE aud esperado no access token

Microsserviços afetados: ecosif-auth, ecosif-masterdata, ecosif-moviments, ecosif-querys, ecosif-reports.


Validação no gateway

Parâmetros JWT (access token)

Claim / parâmetro Valor
Algoritmo RS256
JWKS https://login.microsoftonline.com/{tenant-id}/discovery/v2.0/keys
Issuer (iss) https://login.microsoftonline.com/{tenant-id}/v2.0
Audience (aud) api://{client-id} (= ECOSIF_AZURE_API_AUDIENCE)
Identidade oid (preferencial) ou sub → mapeamento no backend

Rotas públicas (sem access token)

Rotas protegidas

Todas as demais sob /ecosif-* exigem Authorization: Bearer <access_token> válido.

Defense in depth: o gateway e cada microsserviço validam o token. Não confiar apenas na borda.


Azure API Management (referência)

JWT validate policy (HTTP API inbound)

Substitua {tenant-id} e {client-id}:

<inbound>
    <validate-jwt header-name="Authorization" failed-validation-httpcode="401"
                  failed-validation-error-message="Token Microsoft inválido">
        <openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
        <audiences>
            <audience>api://{client-id}</audience>
        </audiences>
        <issuers>
            <issuer>https://login.microsoftonline.com/{tenant-id}/v2.0</issuer>
        </issuers>
    </validate-jwt>
    <base />
</inbound>

Exceções no APIM

Configure operation policies sem validate-jwt para:


AWS API Gateway (HTTP API)

  1. Criar JWT Authorizer: - Issuer: https://login.microsoftonline.com/{tenant-id}/v2.0 - Audience: api://{client-id} - O API Gateway resolve JWKS automaticamente a partir do issuer.
  2. Associar o authorizer às rotas /ecosif-*.
  3. Não associar a POST /ecosif-auth/api/auth/external-login nem signin.
  4. Para rotas mistas (Modo A + B em ambientes diferentes), use APIs/stages separados — não misturar HS256 e RS256 no mesmo authorizer.

Traefik (referência)

Com plugin JWT/OIDC (ex.: traefik-plugin-jwt ou middleware custom):

Parâmetro Valor
jwksUrl https://login.microsoftonline.com/{tenant-id}/discovery/v2.0/keys
issuer https://login.microsoftonline.com/{tenant-id}/v2.0
audience api://{client-id}

Rotas de login e health ficam fora do middleware JWT.


Frontend (Angular)

Componente Comportamento Modo B
login.component.ts MSAL popup → external-login com id_token
api-token-provider.service.ts acquireTokenSilent com scopes de ECOSIF_AZURE_SCOPES
auth.interceptor.ts Envia access_token MSAL; sem refresh via GET /user
Sessão / AuthGuard JWT ECOSIF em localStorage após external-login (bootstrap UI)

Guia frontend: configuracao_provedores.md — Perfil 4.


Checklist de homologação

  1. [ ] App Registration com Expose an API + scope access_as_user + admin consent
  2. [ ] ECOSIF_API_TOKEN_MODE=AZURE_ENTERPRISE_GATEWAY em Angular + 5 backends
  3. [ ] ECOSIF_GWVAL_ACCESSTOKEN_MS=true e ECOSIF_GWVAL_JWT_ECOSIF=false documentados no gateway
  4. [ ] Login Microsoft → external-login retorna 200 + JWT ECOSIF (sessão)
  5. [ ] Chamada GET /ecosif-masterdata/... com access token → 200
  6. [ ] Mesma chamada com JWT ECOSIF → 401 no gateway ou backend
  7. [ ] Token expirado → 401; MSAL renova via acquireTokenSilent
  8. [ ] oid/sub do token existe em identity_provider_link após primeiro login

Verificação no browser (DevTools → Network)


Troubleshooting

Sintoma Causa provável Ação
401 em todas as APIs após login OK aud divergente Conferir ECOSIF_AZURE_API_AUDIENCE = Application ID URI
acquireTokenSilent falha Scope/consent Admin consent em access_as_user; scopes no Angular
401 só no backend, gateway OK Backend em Modo A ECOSIF_API_TOKEN_MODE no container Java
Usuário não encontrado (403) Sem link Verificar identity_provider_link após external-login
401 em external-login Token errado Enviar id_token, não access token

Referências

Documento Conteúdo
gateway_jwt_ecosif.md Modo A — JWT ECOSIF
gateway_access_token_google.md Modo C — Google
variaveis_autenticacao_baseline.md Catálogo ECOSIF_*
runbook_azure_entra.md App Registration Entra
configuracao_provedores.md Angular Modo B
mvp5_integracao_avancada.md Fase 7 / AUTH-09