Os access tokens OAuth 2.0 são as chaves do seu reino de API — e se alguém roubá-los, pode usá-los de qualquer lugar. O DPoP (Demonstrating Proof of Possession), definido na RFC 9449, resolve isso vinculando criptograficamente os tokens ao cliente que os solicitou. Mesmo que um token seja interceptado, ele se torna inútil sem a chave privada do cliente.
A partir do sgcWebSockets 2026.4.0, os componentes cliente e servidor OAuth2 incluem suporte completo a DPoP. Este artigo explica o que é DPoP, como funciona e como configurá-lo no seu aplicativo Delphi.
O que é DPoP?
No OAuth 2.0 padrão, um Bearer token funciona como dinheiro em espécie — quem o possui pode usá-lo. Se um atacante interceptar o token por uma rede comprometida, logs vazados ou um proxy malicioso, ele terá acesso total aos seus recursos protegidos.
O DPoP muda isso fazendo os tokens funcionarem como um cartão de crédito com PIN. O próprio token é vinculado a uma chave pública, e cada requisição deve incluir um JWT de prova assinado pela chave privada correspondente. O servidor verifica se a prova corresponde à chave vinculada antes de aceitar a requisição.
|
Bearer Token (tradicional) Qualquer um com o token pode usá-lo. Tokens roubados são totalmente exploráveis. Não é necessária prova de identidade. |
DPoP Token (restrito ao emissor) O token é vinculado a um par de chaves. Cada requisição requer uma prova assinada recente. Tokens roubados são inúteis sem a chave privada. |
Como o DPoP Funciona
O fluxo DPoP adiciona uma etapa criptográfica leve ao processo OAuth2 padrão:
1. Geração de Chave — O cliente gera um par de chaves assimétrico (ES256 ou RS256). A chave privada fica no cliente; a chave pública é incluída como JWK nas provas DPoP.
2. Requisição de Token — Ao solicitar um access token, o cliente inclui um cabeçalho HTTP DPoP contendo uma prova JWT assinada. A prova inclui o método HTTP, URL, timestamp e um identificador único.
3. Vinculação do Token — O servidor de autorização verifica a assinatura da prova, extrai o thumbprint JWK (hash SHA-256 da chave pública) e vincula ao token emitido. A resposta contém token_type: DPoP em vez de Bearer.
4. Acesso a Recursos — Para cada chamada de API, o cliente envia tanto o token quanto uma prova DPoP recente. A prova inclui uma claim ath (hash SHA-256 do access token), vinculando a prova àquele token específico.
Dentro de uma Prova DPoP
Uma prova DPoP é um JWT compacto com três partes: cabeçalho, payload e assinatura.
// Header - identifies the key and algorithm
{
"typ": "dpop+jwt",
"alg": "ES256",
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "cWs37kZLJMej6fpd...",
"y": "e2bkcQGaBERgSZUb..."
}
}
// Payload - proves freshness and binds to the request
{
"htm": "POST",
"htu": "https://auth.example.com/oauth/token",
"iat": 1774950263,
"jti": "F1AFCD1F-95F7-401B-A2F5-195A31DB1802",
"ath": "fUHyO2r2Z3DZ53EsNr..."
}
Configurando DPoP no sgcWebSockets
Passo 1: Gerar um Par de Chaves ES256
Use o OpenSSL para gerar um par de chaves de curva elíptica:
# Generate EC private key
openssl ecparam -name prime256v1 -genkey -noout -out dpop_private.pem
# Extract public key parameters
openssl ec -in dpop_private.pem -text -noout
Converta as coordenadas X e Y da chave pública para Base64URL para construir o JWK:
{"kty":"EC","crv":"P-256","x":"cWs37kZLJMej6fpdyKaI8Gz6CE...","y":"e2bkcQGaBERgSZUbAGR-iOOM..."}
Passo 2: Configurar o Cliente OAuth2
// Configure OAuth2 as usual
OAuth2.OAuth2Options.GrantType := auth2CodePKCE;
OAuth2.OAuth2Options.ClientId := 'your-client-id';
OAuth2.OAuth2Options.ClientSecret := 'your-client-secret';
OAuth2.AuthorizationServerOptions.AuthURL := 'https://auth.example.com/authorize';
OAuth2.AuthorizationServerOptions.TokenURL := 'https://auth.example.com/oauth/token';
// Enable DPoP
OAuth2.DPoPOptions.Enabled := True;
OAuth2.DPoPOptions.Algorithm := dpopES256;
OAuth2.DPoPOptions.PrivateKey.LoadFromFile('dpop_private.pem');
OAuth2.DPoPOptions.PublicKeyJWK := '{"kty":"EC","crv":"P-256","x":"...","y":"..."}';
// Start the OAuth2 flow - DPoP headers are added automatically
OAuth2.Start;
É isso. O componente automaticamente:
- Gera uma prova DPoP JWT nova para cada requisição de token
- Lida com desafios de servidor
DPoP-Noncee realiza novas tentativas de forma transparente - Armazena o nonce para requisições subsequentes
Passo 3: Usar Provas DPoP para Chamadas de API
Após obter um access token vinculado ao DPoP, gere uma prova para cada requisição de API:
var
vProof: String;
begin
// Generate a DPoP proof for the API call
vProof := OAuth2.GetDPoPProof(
'GET',
'https://api.example.com/userinfo',
OAuth2.AccessToken
);
// Include both headers in your HTTP request:
// Authorization: DPoP <access_token>
// DPoP: <proof_jwt>
HTTPClient.Request.CustomHeaders.AddValue('Authorization',
'DPoP ' + OAuth2.AccessToken);
HTTPClient.Request.CustomHeaders.AddValue('DPoP', vProof);
HTTPClient.Get('https://api.example.com/userinfo');
end;
Provedores Suportados
O DPoP já é suportado pelos principais provedores OAuth2:
| Auth0 | Habilite o DPoP nas configurações do aplicativo. Requer suporte a nonce (tratado automaticamente). |
| Okta | Configure o DPoP nas políticas de acesso do servidor de autorização. Disponível para o público em geral desde 2024. |
| Microsoft Entra ID | Suporta DPoP para clientes confidenciais. |
| Ping Identity | Suporte completo a DPoP no PingOne e PingFederate. |
Validação DPoP no Lado do Servidor
O componente servidor OAuth2 do sgcWebSockets também suporta validação DPoP. Quando OAuth2Options.DPoP está habilitado, o servidor automaticamente:
- Valida JWTs de prova DPoP (assinatura, claims, atualidade)
- Vincula tokens ao thumbprint JWK do cliente
- Retorna
token_type: DPoPpara tokens vinculados ao DPoP - Rejeita requisições com provas inválidas ou ausentes (retorna 400
invalid_dpop_proof) - Verifica a claim
ath(hash do access token) nas requisições a recursos
// Enable DPoP on the OAuth2 server
OAuth2Server.OAuth2Options.DPoP := True;
// Optional: custom validation via event
OAuth2Server.OnOAuth2ValidateDPoP := procedure(Sender: TObject;
Connection: TsgcWSConnection;
const DPoPProof, AccessToken: String;
var IsValid: Boolean)
begin
// Add custom checks here (e.g., verify against a key registry)
IsValid := True;
end;
Referência da API DPoP
| Propriedade / Método | Descrição |
|---|---|
DPoPOptions.Enabled |
Habilita o DPoP para todas as requisições de token. |
DPoPOptions.Algorithm |
dpopES256 (recomendado) ou dpopRS256. |
DPoPOptions.PrivateKey |
Chave privada codificada em PEM para assinar provas DPoP. |
DPoPOptions.PublicKeyJWK |
Representação JSON Web Key da chave pública. |
GetDPoPProof() |
Gera uma prova DPoP JWT para um método HTTP, URL e access token específicos. |
GetDPoPJWKThumbprint() |
Retorna o thumbprint SHA-256 RFC 7638 da chave pública. |
DPoPNonce |
O valor atual de DPoP-Nonce do servidor (somente leitura). |
Melhore a Segurança dos Seus Tokens
O DPoP é a melhoria mais significativa na segurança de tokens OAuth 2.0 desde o PKCE. Ele elimina toda uma classe de ataques de roubo de tokens com alterações mínimas no código — basta definir DPoPOptions.Enabled := True, fornecer suas chaves e o componente sgcWebSockets cuida do resto.
O suporte a DPoP está disponível no sgcWebSockets 2026.4.0 para Delphi (DXE6 ao D13) e .NET (.NET Framework 2.0 ao .NET 9). Baixe a versão mais recente em esegece.com.
