Como projetar sistemas de autenticação federada

1. Fundamentos da Autenticação Federada

A autenticação federada é um mecanismo que permite que usuários acessem múltiplos sistemas ou aplicações utilizando uma única identidade gerenciada por um provedor externo. Os três componentes fundamentais são:

  • Provedor de Identidade (IdP): Responsável por autenticar o usuário e emitir credenciais digitais (tokens, asserções)
  • Provedor de Serviço (SP): A aplicação que consome a identidade federada para conceder acesso
  • Identidade Federada: O vínculo entre a identidade do usuário no IdP e sua conta no SP

Diferentemente do SSO tradicional (que opera dentro de um único domínio administrativo), a federação estabelece confiança entre domínios distintos. Enquanto a autenticação centralizada usa um único banco de usuários, a federação delega a autenticação a terceiros confiáveis.

Casos de uso comuns incluem:
- Login com Google, Facebook ou Apple em aplicações terceiras
- Ambientes corporativos com múltiplas subsidiárias usando um IdP central
- Portais governamentais que integram identidades de diferentes órgãos

2. Protocolos e Padrões Principais

SAML 2.0

O Security Assertion Markup Language (SAML) 2.0 utiliza asserções XML para transportar informações de autenticação. Seus elementos principais:

<saml:Assertion>
  <saml:Issuer>https://idp.exemplo.com</saml:Issuer>
  <saml:Subject>
    <saml:NameID>usuario@exemplo.com</saml:NameID>
  </saml:Subject>
  <saml:Conditions NotBefore="2024-01-01T00:00:00Z"
                   NotOnOrAfter="2024-01-01T01:00:00Z"/>
  <saml:AuthnStatement AuthnInstant="2024-01-01T00:00:00Z"/>
  <saml:AttributeStatement>
    <saml:Attribute Name="email">
      <saml:AttributeValue>joao@exemplo.com</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>
</saml:Assertion>

Fluxos suportados:
- SP-initiated: Usuário acessa o SP, que redireciona ao IdP
- IdP-initiated: Usuário autentica no IdP e é redirecionado ao SP

OpenID Connect (OIDC)

Construído sobre OAuth 2.0, o OIDC adiciona uma camada de identidade. O ID Token (JWT) contém as claims do usuário:

{
  "iss": "https://accounts.google.com",
  "sub": "1234567890",
  "aud": "minha-aplicacao-id",
  "exp": 1704067200,
  "iat": 1704063600,
  "email": "usuario@exemplo.com",
  "email_verified": true
}

Comparação prática

Critério SAML 2.0 OIDC JWT Federado
Formato do token XML JSON (JWT) JSON
Complexidade Alta Média Baixa
Suporte mobile Limitado Nativo Bom
Ecossistema enterprise Maduro Crescente Emergente

Escolha SAML para integrações legadas ou governamentais. Prefira OIDC para aplicações modernas e mobile. Use JWT federado em sistemas internos com confiança pré-estabelecida.

3. Arquitetura de Confiança e Metadados

O estabelecimento de confiança exige:

  1. Certificados e chaves públicas: O SP valida assinaturas do IdP usando sua chave pública
  2. Metadados federados: Documento XML contendo endpoints, certificados e configurações

Exemplo de metadados SAML do SP:

<md:EntityDescriptor entityID="https://sp.exemplo.com/metadata">
  <md:SPSSODescriptor>
    <md:KeyDescriptor use="signing">
      <ds:KeyInfo>
        <ds:X509Certificate>MIIB...==</ds:X509Certificate>
      </ds:KeyInfo>
    </md:KeyDescriptor>
    <md:AssertionConsumerService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
        Location="https://sp.exemplo.com/acs"
        index="1"/>
  </md:SPSSODescriptor>
</md:EntityDescriptor>

Gerenciamento de metadados:
- Estático: Troca manual de arquivos XML entre administradores
- Dinâmico: Uso de Dynamic Discovery ou endpoints de metadados assinados

Para revogação e rotação de chaves, implemente:
- Cache com TTL para metadados (ex: 24 horas)
- Monitoramento de expiração de certificados
- Processo automatizado de rotação com sobreposição de validade

4. Fluxos de Autenticação e Autorização

Fluxo de login federado (OIDC - Authorization Code Flow)

1. Usuário acessa SP e clica em "Login com IdP"
2. SP redireciona para IdP:
   GET /authorize?response_type=code
                  &client_id=sp-client-id
                  &redirect_uri=https://sp.exemplo.com/callback
                  &scope=openid%20email%20profile
                  &state=xyz123

3. Usuário autentica no IdP (login + senha)
4. IdP redireciona de volta ao SP:
   GET /callback?code=auth-code-123&state=xyz123

5. SP troca o código por tokens:
   POST /token
   grant_type=authorization_code
   code=auth-code-123
   client_id=sp-client-id
   client_secret=sp-client-secret

6. IdP retorna ID Token + Access Token
7. SP valida ID Token e cria sessão local

Mapeamento de atributos

Transformação entre claims do IdP e atributos do SP:

// Mapeamento de claims IdP -> SP
{
  "sub": "user_id",
  "email": "email_address",
  "given_name": "first_name",
  "family_name": "last_name",
  "custom:role": "user_role"
}

Autorização federada (ABAC)

Política baseada em atributos federados:

PERMITIR ACESSO SE:
  user.role == "admin" E
  user.department == "engenharia" E
  current_time BETWEEN "09:00" AND "18:00"

5. Segurança e Mitigação de Riscos

Ameaças comuns e contramedidas

Ameaça Mitigação
Sequestro de sessão Uso de state parameter, HttpOnly cookies
Replay de tokens Nonce, timestamps, jti único
CSRF State parameter com hash, SameSite cookies
SAML assertion injection Validação de Audience, Recipient e Destination

Práticas essenciais

// Validação obrigatória no SP
1. Verificar assinatura do token (JWT ou SAML)
2. Validar audience (aud) ou AudienceRestriction
3. Checar expiração (exp, NotOnOrAfter)
4. Confirmar issuer (iss) confiável
5. Validar nonce/state para prevenir replay
6. Verificar se o token não foi revogado (blacklist)

Logs de auditoria federada

{
  "timestamp": "2024-01-01T12:00:00Z",
  "event": "authentication_attempt",
  "user_id": "joao@exemplo.com",
  "idp": "https://accounts.google.com",
  "sp": "https://app.exemplo.com",
  "result": "success",
  "ip_address": "192.168.1.100",
  "session_id": "abc-123-def"
}

6. Projetando para Resiliência e Escalabilidade

Estratégias de failover

// Configuração de múltiplos IdPs
idps:
  primary:
    url: https://idp1.exemplo.com
    metadata: /etc/metadata/idp1.xml
    priority: 1
  secondary:
    url: https://idp2.exemplo.com
    metadata: /etc/metadata/idp2.xml
    priority: 2

// Lógica de failover
SE primary_idp_unavailable THEN
  redirecionar para secondary_idp
  registrar evento de failover

Cache e performance

  • Cache de metadados federados (TTL: 1 hora)
  • Cache de chaves públicas (TTL: 12 horas)
  • Cache de sessões federadas (TTL: conforme política)

Tratamento de timeouts

// Configuração de retry com backoff
retry_policy:
  max_attempts: 3
  initial_delay_ms: 1000
  backoff_multiplier: 2
  max_delay_ms: 10000

// Degradação graciosa
SE idp_unavailable THEN
  exibir mensagem: "Serviço de autenticação temporariamente indisponível"
  oferecer reautenticação em 30 segundos

7. Implementação Prática e Padrões de Código

Estrutura de endpoints do SP

/sp:
  /login            # Inicia fluxo federado
  /callback         # Recebe resposta do IdP
  /logout           # Logout federado (SLO)
  /metadata         # Metadados do SP
  /userinfo         # Informações do usuário autenticado

Exemplo de validação de token JWT/OIDC

// Validação de ID Token
function validar_id_token(token, expected_audience, trusted_issuers):
    // 1. Decodificar header para obter kid
    header = base64_decode(token.header)
    kid = header.kid

    // 2. Buscar chave pública no cache
    public_key = cache.get(kid)
    if public_key is None:
        public_key = fetch_jwks_from_idp()
        cache.set(kid, public_key, ttl=3600)

    // 3. Verificar assinatura
    if not verify_signature(token, public_key):
        throw "Assinatura inválida"

    // 4. Validar claims
    payload = base64_decode(token.payload)

    if payload.iss not in trusted_issuers:
        throw "Issuer não confiável"

    if payload.aud != expected_audience:
        throw "Audience inválida"

    if payload.exp < current_timestamp():
        throw "Token expirado"

    if payload.nonce != session.get('nonce'):
        throw "Nonce inválido"

    return payload

Configuração de trust store

// trust-store.json
{
  "idps": [
    {
      "entity_id": "https://accounts.google.com",
      "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
      "certificates": [
        {
          "kid": "abc123",
          "algorithm": "RS256",
          "expires": "2025-01-01T00:00:00Z"
        }
      ],
      "metadata_url": "https://accounts.google.com/.well-known/openid-configuration"
    }
  ],
  "revocation": {
    "type": "blacklist",
    "endpoint": "https://auth.exemplo.com/revoked-tokens",
    "cache_ttl": 300
  }
}

Boas práticas de logging e monitoramento

// Eventos críticos para monitoramento
- authentication_success: Contagem de logins bem-sucedidos
- authentication_failure: Contagem de falhas por motivo
- token_validation_error: Erros de validação (assinatura, expiração)
- idp_timeout: Timeouts de comunicação com IdP
- certificate_expiring: Certificados próximos da expiração
- metadata_change: Alterações em metadados federados

// Métricas para dashboard
- Taxa de sucesso de autenticação (>99%)
- Latência média de resposta do IdP (<500ms)
- Número de sessões federadas ativas
- Distribuição por IdP utilizado

Testes de integração federada

// Cenários de teste obrigatórios
1. Login bem-sucedido com IdP primário
2. Login com IdP secundário (failover)
3. Token expirado retorna erro 401
4. Token com assinatura inválida retorna erro
5. Audience incorreta é rejeitada
6. Nonce repetido é rejeitado (replay)
7. Logout federado encerra sessão em todos os SPs
8. Rotação de chaves do IdP continua funcionando
9. Timeout do IdP aciona degradação graciosa
10. Metadados expirados forçam recarregamento

Referências