Skip to content

JWT Authentication - Quick Reference Card

📌 Pin this! Referência rápida para consulta durante desenvolvimento


🎯 TL;DR - O Essencial

O QUE: Sistema de autenticação JWT para permitir que usuários autenticados usem o agente sem reautenticar.

POR QUE: Melhor UX, experiência personalizada, segurança.

COMO: JWT enviado no request → validado → injetado na sessão ADK → usado nas tools.

QUANDO: 2-3 semanas de desenvolvimento.


🏗️ Componentes - Lista Rápida

Componente Arquivo Função
🔐 JWT Manager ifriend_agent/session/jwt_context.py Decode + validar
💾 Session Helper ifriend_agent/session/session_context.py Armazenar na sessão
🔄 ContextVar ifriend_agent/session/context_vars.py Thread-safe context
🔑 Auth Manager ifriend_agent/tools/booking/auth.py Usar JWT nas APIs
📡 Adapters messaging/adapters/*.py Extrair JWT
⚙️ Processor messaging/processor.py Integrar tudo

📋 Checklist Ultra-Resumido

Backend

  • [ ] Criar JWTContextManager
  • [ ] Estender Session com jwt_context
  • [ ] Modificar get_auth_headers()
  • [ ] Modificar adapters (WebChat, SSE, WhatsApp, Slack)
  • [ ] Modificar processor
  • [ ] Modificar tools
  • [ ] Testes

Frontend

  • [ ] Enviar JWT no header/body
  • [ ] Renovar token antes de expirar
  • [ ] Tratar erros

💻 Code Snippets - Copy & Paste

Frontend - Enviar JWT (WebChat)

fetch('/webchat/message', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${jwtToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    user_id: userId,
    message: userMessage
  })
});

Backend - Validar JWT

import jwt

payload = jwt.decode(
    token,
    key=JWT_SECRET_KEY,
    algorithms=['HS256'],
    options={'verify_signature': True, 'verify_exp': True}
)

Backend - Usar JWT nas Tools

from ifriend_agent.session.context_vars import current_session_context

# Na tool
ctx = current_session_context.get()
if ctx:
    session_ctx = await get_session_context(...)
    headers = await get_auth_headers(session_context=session_ctx)
else:
    headers = await get_auth_headers()  # Fallback

🔐 JWT Format

Claims Obrigatórios

{
  "sub": "user_789",
  "email": "user@example.com",
  "exp": 1707955800
}

Claims Recomendados

{
  "name": "João Silva",
  "roles": ["traveler"],
  "iat": 1707869400,
  "iss": "https://theifriend.com",
  "aud": "ifriend-api"
}

⚙️ Configuração - .env

# Obrigatórios
JWT_SECRET_KEY=your-secret-key-256-bits
JWT_ALGORITHM=HS256

# Opcionais (defaults)
JWT_VERIFY_SIGNATURE=true
JWT_VERIFY_EXP=true
JWT_ISSUER=https://theifriend.com
JWT_AUDIENCE=ifriend-api

🔄 Fluxo Simplificado

1. Cliente envia mensagem + JWT
         ↓
2. Adapter extrai JWT → metadata
         ↓
3. Processor valida JWT → UserContext
         ↓
4. Injeta em session.metadata.jwt_context
         ↓
5. Tool lê ContextVar → get JWT
         ↓
6. Usa JWT na API call
         ↓
7. Resposta autenticada retorna

🚨 Troubleshooting Rápido

Sintoma Causa Solução
"Token expired" JWT expirado Frontend renova token antes de expirar
"Invalid signature" Secret errado Verifica JWT_SECRET_KEY igual em ambos lados
"Token malformed" JWT incompleto Verifica formato: header.payload.signature
JWT não funciona Adapter não extrai Debug: log message.metadata
Tool usa auth default Session context não tem JWT Debug: verifica session.metadata.jwt_context

📊 Comandos Úteis - Testing

Gerar JWT de Teste

# Python
python -c "import jwt; print(jwt.encode({'sub':'u123','email':'test@test.com','exp':9999999999}, 'secret', algorithm='HS256'))"

Decodificar JWT

# Usando jwt.io ou:
echo "eyJhbGc..." | cut -d. -f2 | base64 -d | jq

Testar com cURL

JWT="eyJhbGc..."
curl -X POST http://localhost:8080/webchat/message \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"u123","message":"Olá"}'

Verificar JWT no Redis (WhatsApp/Slack)

redis-cli GET "whatsapp:jwt:+5511999999999"
redis-cli GET "slack:jwt:U123ABC"

🎨 Plataformas - Strategy Resumida

Plataforma Como Enviar JWT Método
WebChat Header Authorization ou body jwt_token Direto
SSE Header Authorization no POST inicial Direto
WhatsApp Vincular via web → lookup Redis Cache
Slack Comando /ifriend-auth <JWT> → lookup Redis Cache

✅ Validation Checklist

JWT É Válido Se:

  • [ ] Tem 3 partes separadas por ponto (header.payload.signature)
  • [ ] Assinatura válida (verifica com JWT_SECRET_KEY)
  • [ ] Não expirado (exp > now)
  • [ ] Claims obrigatórios presentes (sub, email, exp)
  • [ ] Issuer correto (se configurado)
  • [ ] Audience correto (se configurado)

Session Context Está OK Se:

  • [ ] session.metadata existe
  • [ ] session.metadata.jwt_context existe
  • [ ] jwt_context.has_jwt == true
  • [ ] jwt_context.token presente
  • [ ] jwt_context.user_id presente

📈 Métricas - O Que Monitorar

Durante Dev

  • Coverage de testes: >85%
  • Testes passando: 100%

Durante Deploy

  • Taxa de adoção JWT: >80%
  • Taxa de erro JWT: <1%
  • Latência JWT decode: <50ms


🆘 Stuck? Perguntas Rápidas

Q: JWT não está sendo usado nas tools?
A: Verifica: (1) JWT no metadata? (2) Session context injetado? (3) ContextVar configurado? (4) Tool lê ContextVar?

Q: Sempre usa auth default?
A: Debug session.metadata.jwt_context. Provavelmente: JWT inválido, não foi injetado, ou ContextVar não está setado.

Q: Performance ruim?
A: JWT decode está em cache? ContextVar é thread-safe e rápido. Não decodifique em cada tool call.

Q: WhatsApp/Slack não funciona?
A: (1) Usuário vinculou? (2) Redis tem o mapping? (3) Adapter faz lookup? (4) TTL expirou?

Q: Teste manual não funciona?
A: (1) JWT válido? (2) Secret correto? (3) Header formato: Bearer <token>? (4) Backend rodando?


🚀 Quick Start - 3 Passos

1. Backend Setup

# Instalar dependência
pip install PyJWT>=2.8.0

# Configurar .env
echo "JWT_SECRET_KEY=sua-chave-secreta" >> .env

2. Implementar Componentes

# Criar arquivos base
touch ifriend_agent/session/jwt_context.py
touch ifriend_agent/session/session_context.py
touch ifriend_agent/session/context_vars.py

# Modificar adapters
vim messaging/adapters/webchat_adapter.py

3. Testar

# Rodar testes
pytest tests/unit/test_jwt_*.py
pytest tests/integration/test_*_jwt.py

# Teste manual
curl -X POST http://localhost:8080/webchat/message \
  -H "Authorization: Bearer eyJhbGc..." \
  -d '{"user_id":"test","message":"Olá"}'

💡 Pro Tips

  1. Sempre valide signature - Segurança primeiro!
  2. Cache tokens decodificados - Performance
  3. Fallback para auth default - Disponibilidade
  4. Nunca logue token completo - Segurança
  5. Use ContextVar - Thread-safe e clean
  6. TTL de 24h no JWT - Balance UX e segurança
  7. Monitore taxa de erro - <1% é saudável

🎓 Conceitos-Chave - 1 Linha Cada

  • JWT: Token assinado com claims do usuário
  • UserContext: Claims decodificados (user_id, email, etc.)
  • Session Context: Metadata da sessão ADK
  • ContextVar: Thread-safe context storage (Python)
  • Lookup: Cache Redis para WhatsApp/Slack
  • Fallback: Usar auth default se JWT falhar
  • Backward Compatible: Apps sem JWT continuam funcionando

📌 Bookmark this page!
Consulte sempre que precisar durante o desenvolvimento


Versão: 1.0
Última Atualização: 13/02/2026
Mantenedor: Tech Lead iFriend Agents