Fluxo de Autenticação
Diagrama
sequenceDiagram
participant S as Fornecedor
participant A as API Hub
participant DB as PostgreSQL
Note over S,A: 1. Emissão (uma vez, ou após expiração do refresh)
S->>A: POST /api/external-auth/token<br/>x-api-key: <chave-fixa>
A->>DB: Carrega suppliers ativos
A->>A: Verifica hash PBKDF2 (tempo constante)
A->>DB: Persiste refresh token (hashed)
A-->>S: { access_token, refresh_token }
Note over S,A: 2. Chamadas de negócio (~15 min)
S->>A: GET /api/external/ping<br/>Authorization: Bearer <access_token>
A->>A: Valida JWT (issuer, audience, exp, assinatura)
A-->>S: 200 OK
Note over S,A: 3. Renovação (quando access_token expira)
S->>A: POST /api/external-auth/refresh<br/>{ "refreshToken": "..." }
A->>DB: Busca por hash do refresh token
A->>A: Verifica: não revogado, não expirado
A->>DB: Revoga token antigo (rotation)
A->>DB: Persiste novo refresh token (hashed)
A-->>S: { access_token, refresh_token } (novos)
Note over S,A: 4. Encerramento de sessão
S->>A: POST /api/external-auth/revoke<br/>{ "refreshToken": "..." }
A->>DB: Marca como revogado
A-->>S: 204 No Content
Estados do refresh token
ATIVO
│
├── /refresh ──► REVOGADO (reason: "rotation")
│ + novo token ATIVO criado
│
├── /revoke ──► REVOGADO (reason: "manual-revoke")
│
└── expirou ──► EXPIRADO (passivo)
REVOGADO apresentado em /refresh:
└── REUSE DETECTED ──► todos os tokens ATIVOS do supplier são REVOGADOS
(reason: "reuse-detected")
Supplier precisa se re-autenticar com a API key
Reuse detection
Se um refresh token já revogado for apresentado novamente, o sistema assume que houve roubo de token e encerra toda a sessão do fornecedor:
- Loga warning com
supplierId+ IP (nunca o token em si). - Carrega todos os tokens ativos do fornecedor.
- Revoga todos com
RevocationReason = "reuse-detected". - Retorna
401 invalid_grant.
O fornecedor precisa usar a API key novamente para iniciar uma nova sessão.