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 |
| 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
🔗 Links Rápidos¶
- 📖 Documentação Completa
- 🗺️ Mapa de Navegação
- 📊 Resumo Executivo
- 🏗️ Plano Detalhado
- 💻 Exemplos Frontend
- 🤔 Decisões Técnicas
- 🔄 Diagramas
- ✅ Checklist
🆘 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¶
- Sempre valide signature - Segurança primeiro!
- Cache tokens decodificados - Performance
- Fallback para auth default - Disponibilidade
- Nunca logue token completo - Segurança
- Use ContextVar - Thread-safe e clean
- TTL de 24h no JWT - Balance UX e segurança
- 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