OAuth2 dPoP Delphi

· Recursos

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:

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:

// 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.