Ambiente de demonstração do padrão de tokens one-shot e opacos para endpoints de movimentação financeira.
- Docker e Docker Compose instalados
docker compose up --buildA API sobe em http://localhost:8000.
A documentação interativa (Swagger UI) fica em http://localhost:8000/docs.
As chamadas abaixo usam curl. Você também pode executar tudo pelo Swagger UI.
curl http://localhost:8000/debug/sessionscurl -s -X POST http://localhost:8000/operation-tokens \
-H "Authorization: Bearer session-joao-abc123" \
-H "Content-Type: application/json" \
-d '{
"operation": "transfer",
"amount": 500.00,
"destination": "12345-6",
"intent_hash": "abc123demo"
}' | python3 -m json.toolGuarde o valor de operation_token retornado.
curl http://localhost:8000/debug/tokenscurl -s -X POST http://localhost:8000/transfers \
-H "Authorization: Bearer session-joao-abc123" \
-H "X-Operation-Token: <TOKEN_DA_FASE_1>" \
-H "Content-Type: application/json" \
-d '{
"amount": 500.00,
"destination": "12345-6"
}' | python3 -m json.toolcurl -s -X POST http://localhost:8000/transfers \
-H "Authorization: Bearer session-joao-abc123" \
-H "X-Operation-Token: <MESMO_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"amount": 500.00,
"destination": "12345-6"
}' | python3 -m json.tool
# Esperado: 401 — Token inválido, já utilizado ou expirado# Gere um novo token para R$ 500
curl -s -X POST http://localhost:8000/operation-tokens \
-H "Authorization: Bearer session-joao-abc123" \
-H "Content-Type: application/json" \
-d '{
"operation": "transfer",
"amount": 500.00,
"destination": "12345-6",
"intent_hash": "abc123demo"
}' | python3 -m json.tool
# Tente executar com R$ 5000
curl -s -X POST http://localhost:8000/transfers \
-H "Authorization: Bearer session-joao-abc123" \
-H "X-Operation-Token: <TOKEN_ACIMA>" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000.00,
"destination": "12345-6"
}' | python3 -m json.tool
# Esperado: 422 — Parâmetro diverge do declarado na Fase 1# Gere um token
TOKEN=$(curl -s -X POST http://localhost:8000/operation-tokens \
-H "Authorization: Bearer session-joao-abc123" \
-H "Content-Type: application/json" \
-d '{"operation":"transfer","amount":100.00,"destination":"99999-0","intent_hash":"xyz"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['operation_token'])")
echo "Token gerado: $TOKEN"
# Force a expiração
curl -s -X POST http://localhost:8000/debug/tokens/expire \
-H "Content-Type: application/json" \
-d "{\"operation_token\": \"$TOKEN\"}" | python3 -m json.tool
# Tente usar o token expirado
curl -s -X POST http://localhost:8000/transfers \
-H "Authorization: Bearer session-joao-abc123" \
-H "X-Operation-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount": 100.00, "destination": "99999-0"}' | python3 -m json.tool
# Esperado: 401# João gera um operation token
TOKEN=$(curl -s -X POST http://localhost:8000/operation-tokens \
-H "Authorization: Bearer session-joao-abc123" \
-H "Content-Type: application/json" \
-d '{"operation":"transfer","amount":200.00,"destination":"77777-7","intent_hash":"stolen"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin)['operation_token'])")
echo "Token do João: $TOKEN"
# Atacante tenta usar o token do João com a própria sessão
curl -s -X POST http://localhost:8000/transfers \
-H "Authorization: Bearer session-atacante-eve000" \
-H "X-Operation-Token: $TOKEN" \
-H "Content-Type: application/json" \
-d '{"amount": 200.00, "destination": "77777-7"}' | python3 -m json.tool
# Esperado: 403 — Operation token pertence a outro usuáriostub/
├── docker-compose.yml # Orquestra API + Redis
├── Dockerfile # Imagem da API
├── requirements.txt # Dependências Python
├── README.md
└── app/
├── main.py # Rotas FastAPI
├── models.py # Schemas Pydantic
├── config.py # Configurações via env vars
├── security.py # Geração de token opaco + intent hash
├── token_store.py # Operações Redis (store / fetch+invalidate / debug)
└── sessions.py # Sessões fake pré-configuradas para demo
| Variável | Padrão | Descrição |
|---|---|---|
REDIS_URL |
redis://localhost:6379 |
URL de conexão com o Redis |
SESSION_SECRET |
dev-secret-... |
Segredo de sessão (não usado em produção aqui) |
OPERATION_TOKEN_TTL |
120 |
Tempo de vida do operation token em segundos |