Files
Enterprise-MCP-Service-Bus/RI/docs/interfaces/identity-oidc.md
2026-09-14 14:01:27 -03:00

3.3 KiB

Interface: identidade e registro de MCP Client (OIDC)

Contrato de registro de um MCP Client e do token OIDC que ele apresenta ao Gateway. Implementação: src/emcp_bus/identity/models.py, identity/authn.py, identity/shared_client_lint.py. Ver AS-BUILT.md.

Registro de um MCP Client

Um arquivo YAML por client em config/clients/*.yaml, validado contra ClientRegistration:

client_id: finance-payments-agent   # exatamente a claim azp/client_id do token
profile: Finance.Payments           # nome de um ClientProfile em config/clients/profiles/
environment: production             # "dev" | "ci" | "production"
description: "Finance agent authorized to create/execute payments (R3, approval above threshold)"

(exemplo real: config/clients/finance-payments-agent.yaml)

client_id é o único vínculo entre uma identidade autenticada e um ClientProfile — dois client_ids distintos nunca compartilham profile a menos que isso seja uma decisão explícita e auditável (regra de shared client, identity/shared_client_lint.py, ligada a make validate-schemas).

Registro do client no IdP

O client precisa existir no realm do IdP com o grant client_credentials habilitado e um mapper de audience apontando para o OIDC_AUDIENCE do Gateway (emcp-gateway por padrão). Ver deploy/keycloak/realm-export.json para os 3 clients de exemplo já configurados dessa forma (sales-read-agent, sales-write-agent, finance-payments-agent).

Contrato do token de acesso

Qualquer IdP compatível com OIDC funciona (TokenValidator é agnóstico de fornecedor). Claims exigidas e validadas por TokenValidator.validate:

Claim Uso
exp Expiração — obrigatória, validada com leeway_seconds=5.
iss Deve casar exatamente com OIDC_ISSUER.
aud Deve conter OIDC_AUDIENCE.
azp (preferencial) ou client_id Fonte única de identidade do client — nunca clientInfo do request MCP nem qualquer campo do corpo.

Assinatura verificada via JWKS (OIDC_JWKS_URL), algoritmo RS256. Falha em qualquer checagem levanta AuthenticationError, tratada pelo Gateway como UNAUTHENTICATED (fail-closed).

Como um novo client se registra, ponta a ponta

  1. Criar/atualizar o client no IdP (grant client_credentials, mapper de audience).
  2. Criar config/clients/<client-id>.yaml (ClientRegistration).
  3. Apontar profile para um ClientProfile existente, ou criar um novo em config/clients/profiles/ (ver registry-capability-manifest.md para como uma capability referencia um profile via entitlements).
  4. make validate-schemas.
  5. Reiniciar o Gateway (registros de client são carregados no boot, sem hot-reload).

Erros

Situação Comportamento
Token ausente/malformado/expirado/assinatura inválida AuthenticationError → Gateway trata como UNAUTHENTICATED.
aud/iss incorretos AuthenticationError → UNAUTHENTICATED (README.md §45 Teste 8).
Token válido, mas client_id sem ClientRegistration correspondente UnknownClientError → Gateway responde UNKNOWN_CLIENT em tools/call, lista vazia em tools/list.