OIDC Session Metadata e Zero Trust: Uma Decisão de Arquitetura
Ouvir estudo
gerado ao ouvirGerado apenas no primeiro play
Com tecnologia Amazon Polly + OmniVoice
O suporte a metadados de sessão no Sign in with Google abre uma janela real para acesso adaptativo baseado em sinais de identidade contínuos — não apenas no momento do login. Neste ADR, analiso as forças arquiteturais, as opções consideradas e a decisão que tomaria em um sistema financeiro de alta criticidade integrado à AWS.
Por anos, tratamos a sessão autenticada como um estado binário: o usuário fez login ou não. O suporte a metadados de sessão no Sign in with Google muda essa equação ao expor sinais contínuos de identidade — risco de conta, estado de verificação, alterações recentes de credencial — diretamente no fluxo OIDC. Para sistemas financeiros que operam sob Zero Trust, isso não é uma feature de conveniência; é uma mudança de modelo de ameaça. A questão arquitetural real não é 'como integrar isso ao Cognito', mas sim 'onde na minha cadeia de autorização esses sinais devem ser avaliados, com que latência, e o que acontece quando o provedor de identidade não os entrega?'
Contexto e Forças: Por Que Isso Importa Agora
Em ambientes financeiros regulados — PCI-DSS, SOC 2 Type II, BACEN 4.658 no Brasil — a autenticação federada com provedores externos como Google sempre foi uma faca de dois gumes. Você ganha UX e reduz a superfície de gerenciamento de credenciais, mas perde visibilidade sobre o ciclo de vida da sessão do usuário no lado do IdP. Um token JWT válido emitido às 09h00 ainda é aceito às 17h00 mesmo que o usuário tenha trocado a senha às 14h00, que o Google tenha detectado acesso suspeito à conta às 15h00, ou que o dispositivo tenha sido marcado como comprometido às 16h00.
O modelo tradicional de mitigação era simples e brutal: tokens de curta duração (15-30 minutos) com refresh agressivo. Isso funciona, mas tem custo: latência de re-autenticação, fricção em fluxos de longa duração (relatórios, exportações, operações batch iniciadas pelo usuário), e pressão sobre os rate limits do Cognito — que impõe 120 requisições de token por segundo por user pool por padrão, um limite que sistemas de médio porte atingem facilmente em horários de pico.
Metadados de sessão OIDC mudam o vetor de defesa. Em vez de encurtar a vida do token, você enriquece a decisão de autorização com sinais do IdP em tempo real. O token pode ter vida mais longa, mas cada requisição sensível passa por uma avaliação que considera o estado atual da sessão no Google — não apenas o estado no momento da emissão. Isso é, conceitualmente, o que o NIST SP 800-207 chama de 'continuous verification' dentro de um modelo Zero Trust.
As Forças em Tensão
Antes de chegar às opções, é preciso nomear as forças que tornam essa decisão não trivial:
Latência vs. Frescor do Sinal. Consultar metadados de sessão do Google a cada requisição adiciona uma chamada de rede externa ao caminho crítico. Em APIs financeiras com SLO de p99 < 300ms, isso é inaceitável sem cache. Mas cache introduz janela de staleness — exatamente o problema que estamos tentando resolver.
Disponibilidade do IdP vs. Continuidade do Serviço. Se o endpoint de metadados do Google estiver indisponível, o que fazemos? Fail-open (aceitar a requisição) ou fail-closed (negar)? Em sistemas financeiros, fail-closed é o padrão regulatório correto, mas isso significa que uma degradação do Google pode derrubar seu serviço.
Granularidade de Política vs. Complexidade Operacional. Quanto mais granular a política de acesso adaptativo — 'este endpoint requer score de risco < 20 E verificação de dispositivo recente' — mais difícil é depurar, auditar e explicar para times de compliance.
Cobertura de Claims vs. Dependência de Vendor. Os metadados que o Google expõe são proprietários. Se amanhã você precisar suportar Microsoft Entra ou Okta como IdP alternativo, sua lógica de política precisa abstrair sobre diferentes schemas de claims. Isso é um risco de lock-in que poucos times de arquitetura modelam explicitamente.
Essas quatro tensões definem o espaço de design. As opções abaixo são respostas diferentes para o mesmo conjunto de forças.
Opções Consideradas para Avaliação de Metadados de Sessão
Opção A: Token de Curta Duração (Status Quo)
- Sem dependência de endpoint externo no caminho crítico
- Simples de implementar e auditar
- Comportamento previsível em falhas do IdP
- Janela de risco entre revogação no IdP e expiração do token
- Pressão sobre rate limits do Cognito em escala
- Fricção em fluxos de longa duração
Adequado para sistemas de baixo risco; insuficiente para operações financeiras críticas
Opção B: Avaliação Inline no Lambda Authorizer
- Sinal mais fresco possível por requisição
- Política centralizada e auditável no authorizer
- Integração natural com API Gateway e ALB
- Latência adicionada: p99 de chamada ao Google ~80-150ms sem cache
- Disponibilidade do serviço acoplada ao Google
- Cold start do Lambda amplifica latência em picos
Viável com cache agressivo e circuit breaker; requer SLO de latência revisado
Opção C: Avaliação Assíncrona com Step-Up Reativo
- Zero latência adicionada ao caminho crítico
- Degradação graciosa quando o Google está indisponível
- Permite políticas diferenciadas por nível de sensibilidade da operação
- Janela de risco entre detecção assíncrona e revogação da sessão
- Maior complexidade: EventBridge + Step Functions + DynamoDB
- Requer lógica de step-up no cliente (redirecionamento para re-auth)
Melhor equilíbrio para sistemas financeiros de alta escala; é a opção que eu escolheria
Opção D: Abstração via IDSA/SPIFFE com Claims Normalizados
- Elimina lock-in em schema proprietário do Google
- Portabilidade entre IdPs (Entra, Okta, Google)
- Alinha com padrões de identidade de workload (SPIFFE/SPIRE)
- Overhead de implementação significativo; requer camada de tradução de claims
- Maturidade operacional alta exigida do time
- Fora do escopo para a maioria dos projetos em 2025
Ideal como visão de longo prazo; prematuro como primeira implementação
A Decisão: Avaliação Assíncrona com Step-Up Síncrono Seletivo
Depois de modelar as quatro opções contra as forças identificadas, a decisão que eu tomaria é uma variante da Opção C com um elemento síncrono cirúrgico: avaliação assíncrona de metadados de sessão para a maioria das requisições, com step-up síncrono obrigatório para operações de alto impacto financeiro.
A lógica é a seguinte: nem todas as requisições têm o mesmo perfil de risco. Uma consulta de saldo ou leitura de extrato tem tolerância a uma janela de staleness de 5 minutos no sinal de risco. Uma transferência acima de R$ 10.000, uma alteração de dados cadastrais ou uma aprovação de crédito não têm. Forçar o mesmo modelo de avaliação para ambas é over-engineering no primeiro caso e under-engineering no segundo.
A implementação concreta usa três componentes AWS em coordenação:
- DynamoDB como cache de estado de sessão: chave de partição
userId#sessionId, TTL de 5 minutos, com atributosriskScore,verificationState,lastMetadataRefreshestepUpRequired. Capacidade provisionada com auto-scaling: 100 RCU/WCU base, escala até 2.000 em pico. Criptografia com KMS CMK, ponto-a-ponto.
- Lambda Authorizer com leitura síncrona do DynamoDB: o authorizer lê o estado de sessão cacheado (latência p99 < 5ms com DAX opcional) e toma a decisão de autorização localmente. Não há chamada ao Google no caminho crítico. Se
stepUpRequired = true, retorna 401 comWWW-Authenticate: step-upe o cliente inicia o fluxo de re-autenticação.
- EventBridge Scheduler + Lambda de refresh assíncrono: a cada 4 minutos, um job consulta o endpoint de metadados do Google para sessões ativas e atualiza o DynamoDB. Se o sinal de risco mudar, o atributo
stepUpRequiredé setado atomicamente com uma condição DynamoDB (ConditionExpression: attribute_not_exists(stepUpRequired) OR stepUpRequired = :false), evitando race conditions.
Fluxo de Avaliação de Metadados de Sessão OIDC com Step-Up Adaptativo
Caminho crítico (síncrono) à esquerda; pipeline de refresh assíncrono à direita. O Lambda Authorizer nunca chama o Google diretamente — lê apenas do cache DynamoDB.
- API Gateway · REST / HTTP API
- Lambda Authorizer · step-up policy eval
- DynamoDB · userId#sessionId / TTL 5m
- KMS CMK · encrypt at rest
- EventBridge Scheduler · every 4 min
- Refresh Lambda · fetch + diff + write
- Step Functions · step-up orchestration
- CloudWatch · stepUpRate / riskSignalAge
- Sign in with Google · OIDC + session metadata
- Financial API · Lambda / EKS
Detalhes de Implementação que Importam em Produção
IAM e Least Privilege no Lambda Authorizer. O authorizer precisa apenas de dynamodb:GetItem na tabela de sessões, com condição aws:ResourceTag/Classification = SessionCache. Nenhuma permissão de escrita. A role do refresh Lambda tem dynamodb:UpdateItem com condição dynamodb:LeadingKeys restrita ao prefixo userId# — impedindo que um bug no código escreva em partições arbitrárias. Ambas as roles usam kms:Decrypt com condição kms:EncryptionContext:TableName = session-state.
Circuit Breaker no Refresh Lambda. A chamada ao endpoint de metadados do Google deve ter timeout de 2 segundos e no máximo 2 retries com backoff exponencial. Se a taxa de erro superar 50% em uma janela de 60 segundos, o circuit breaker abre e o refresh Lambda para de tentar — mas não seta stepUpRequired = true automaticamente. A política correta aqui é conservar o último estado conhecido e emitir um alarme CloudWatch (MetricName: GoogleMetadataUnavailable, threshold > 3 minutos). A decisão de fail-open vs. fail-closed durante indisponibilidade do Google deve ser explícita na política e documentada no ADR — não implícita no código.
Observabilidade do Sinal de Risco. Os metadados do Google incluem campos como credential_age, account_risk_level e device_verified. Esses valores devem ser emitidos como dimensões de métricas customizadas no CloudWatch — não apenas logados. Isso permite criar alarmes como 'percentual de sessões ativas com account_risk_level = HIGH > 5%', que é um sinal de ataque de credential stuffing em andamento. O SLO que eu definiria: riskSignalAge (tempo desde o último refresh bem-sucedido) < 6 minutos para 99% das sessões ativas.
Cognito User Pools e o Problema do Token Opaco. O Cognito não repassa claims customizados do Google automaticamente para o access token. Você precisa de um Lambda trigger Pre Token Generation que leia o estado de sessão do DynamoDB e injete os claims relevantes. Atenção: esse trigger adiciona latência ao fluxo de refresh de token — mantenha-o abaixo de 100ms ou o Cognito vai timeout na chamada.
Consequências e Riscos da Decisão
Janela de risco residual de até 4 minutos. A arquitetura assíncrona aceita explicitamente que um usuário com sessão comprometida pode fazer até ~4 minutos de requisições de baixo impacto antes de ser bloqueado. Para operações de alto impacto, o step-up síncrono elimina essa janela — mas o time de compliance precisa aceitar e documentar esse trade-off formalmente. Não tente esconder isso no design.
Dependência de disponibilidade do Google para o pipeline de refresh. Se o Google tiver uma degradação de 30 minutos, o riskSignalAge vai ultrapassar o SLO. Você precisa de um runbook explícito: o que o sistema faz automaticamente (conserva último estado), o que o operador faz manualmente (pode forçar step-up global via feature flag no DynamoDB), e quando escalar para o time de segurança.
Custo de DynamoDB em escala. Com 100.000 sessões ativas e refresh a cada 4 minutos, o pipeline assíncrono gera ~25.000 writes/minuto. No modo on-demand, isso é ~$0.0000125 por write = ~$0.31/minuto = ~$450/mês apenas para o refresh pipeline. Não é caro, mas precisa estar no modelo de custo — especialmente se o número de sessões escalar 10x.
Risco de amplificação de step-up. Se o Google retornar account_risk_level = HIGH para um segmento grande de usuários simultaneamente (falso positivo em massa), você pode acionar step-up para milhares de usuários ao mesmo tempo, gerando uma avalanche de re-autenticações que sobrecarrega o Cognito. Implemente rate limiting no número de step-ups simultâneos e um mecanismo de override de emergência.
Governança, Auditoria e o Caminho para Zero Trust Maduro
Uma decisão de arquitetura de identidade não termina na implementação técnica. Em sistemas financeiros regulados, a rastreabilidade de cada decisão de autorização é tão importante quanto a decisão em si. Cada chamada ao Lambda Authorizer deve emitir um evento estruturado para o CloudWatch Logs com: userId, sessionId, decision (allow/deny/step-up), riskScore no momento da decisão, signalAge em segundos, e o requestId do API Gateway. Esse log é a evidência de auditoria para demonstrar ao regulador que o sistema estava operando com verificação contínua.
No contexto do AWS Well-Architected, essa arquitetura toca diretamente o pilar de Segurança — especificamente os princípios de 'apply security at all layers' e 'enable traceability'. O uso de KMS CMK com rotation anual, IAM conditions granulares, e CloudTrail habilitado para todas as operações DynamoDB e KMS fecha o loop de auditoria.
O caminho para Zero Trust maduro a partir daqui tem dois passos naturais. O primeiro é adicionar sinais de contexto de dispositivo — não apenas o que o Google sabe sobre a conta, mas o que você sabe sobre o dispositivo: fingerprint, geolocalização, padrão de comportamento. Isso pode ser implementado via Amazon Fraud Detector ou via um modelo customizado no SageMaker alimentado pelos logs de auditoria. O segundo é mover a política de autorização para um motor externo — Open Policy Agent (OPA) rodando no EKS, ou AWS Verified Permissions com Cedar — desacoplando a lógica de política do código do authorizer e permitindo que o time de compliance edite políticas sem deploy de código.
Essa evolução deve estar no roadmap, mas não no MVP. A armadilha clássica é tentar construir o sistema Zero Trust completo na primeira iteração e não entregar nada.
Avaliação pelos Pilares Well-Architected
Segurança
Verificação contínua de sessão via metadados OIDC, KMS CMK, IAM least-privilege com condições granulares, CloudTrail para auditoria completa. Step-up síncrono para operações de alto impacto elimina a janela de risco nas operações críticas.
Confiabilidade
Circuit breaker no refresh Lambda protege contra indisponibilidade do Google. Estado de sessão cacheado no DynamoDB garante que o authorizer funcione mesmo sem conectividade ao IdP. Runbook explícito para degradação do sinal.
Eficiência de performance
Lambda Authorizer lê apenas do DynamoDB (p99 < 5ms com DAX). Nenhuma chamada ao Google no caminho crítico. Cache TTL de 5 minutos balanceia frescor e latência.
Anti-Padrões a Evitar
- Chamar o endpoint de metadados do Google diretamente no Lambda Authorizer sem cache — você vai violar seu SLO de latência e acoplar disponibilidade ao Google.
- Tratar
account_risk_levelcomo binário (alto/baixo) sem considerar a distribuição histórica — um threshold fixo vai gerar falsos positivos em eventos de segurança legítimos do Google (ex: mudança de senha voluntária). - Armazenar o token OIDC completo no DynamoDB como estado de sessão — armazene apenas os claims relevantes para a política, nunca o token bruto.
- Não documentar explicitamente a janela de risco residual no ADR — o time de compliance vai descobrir isso em uma auditoria e será pior.
- Usar o mesmo Lambda Authorizer para todos os endpoints sem diferenciar sensibilidade — aplique step-up síncrono apenas onde o risco justifica a latência adicional.
Na prática, a decisão mais difícil aqui não é técnica — é política: convencer o time de compliance a aceitar formalmente uma janela de risco de 4 minutos em troca de um sistema que é auditável, observável e que não quebra quando o Google tem uma degradação. Já vi times construírem sistemas de avaliação síncrona 'perfeitos' que ficaram indisponíveis por 45 minutos durante um incidente do Google e ninguém havia documentado o fallback. O circuit breaker e o runbook explícito não são detalhes de implementação — são o núcleo da decisão arquitetural. E o ADR precisa viver no repositório, não em uma wiki que ninguém lê depois do go-live.
Veredicto: Adote Metadados de Sessão OIDC com Avaliação Assíncrona e Step-Up Seletivo
O suporte a metadados de sessão no Sign in with Google é um avanço real para sistemas que precisam de verificação contínua de identidade. A decisão correta para ambientes financeiros não é avaliação síncrona em cada requisição — é avaliação assíncrona com cache DynamoDB, circuit breaker explícito, e step-up síncrono cirúrgico para operações de alto impacto. Essa arquitetura entrega Zero Trust prático: verificação contínua sem sacrificar latência, com degradação graciosa e auditabilidade completa. A janela de risco residual de 4 minutos é um trade-off aceitável e documentável — não uma falha de design. Implemente, documente no ADR, e evolua para AWS Verified Permissions com Cedar quando a maturidade do time permitir.
Referências
Post-mortems, ADRs e deep dives de arquitetura no seu email — do jeito que um arquiteto lê.
Sem spam · cancele quando quiser
Pergunte ao Fernando sobre isto
Receba uma resposta focada sobre este estudo do meu assistente de IA, baseada no meu trabalho.
Participe da conversa
Entre para comentar
Confirme seu e-mail para participar — você também recebe a newsletter. Sem senha.