OAuth2 DPoP in Delphi

· Functies

OAuth 2.0-access-tokens zijn de sleutels tot je API-koninkrijk — en als iemand er een steelt, kan hij die overal gebruiken. DPoP (Demonstrating Proof of Possession), gedefinieerd in RFC 9449, lost dit op door tokens cryptografisch te koppelen aan de client die ze heeft aangevraagd. Zelfs als een token wordt onderschept, is het zonder de private sleutel van de client waardeloos.

Vanaf sgcWebSockets 2026.4.0 bevatten de OAuth2-client- en servercomponenten volledige DPoP-ondersteuning. Dit artikel legt uit wat DPoP is, hoe het werkt en hoe je het in je Delphi-applicatie configureert.

Wat is DPoP?

In standaard OAuth 2.0 werkt een Bearer-token als contant geld — wie het heeft, kan het uitgeven. Als een aanvaller het token onderschept via een gecompromitteerd netwerk, gelekte logs of een kwaadaardige proxy, heeft hij volledige toegang tot je beschermde resources.

DPoP verandert dat door tokens te laten werken als een creditcard met pincode. Het token zelf is gekoppeld aan een public key en elke aanvraag moet een proof-JWT bevatten die is ondertekend met de bijbehorende private key. De server controleert of de proof overeenkomt met de gekoppelde sleutel voordat hij de aanvraag accepteert.

Bearer-token (traditioneel)
Iedereen met het token kan het gebruiken. Gestolen tokens zijn volledig misbruikbaar. Geen identiteitsbewijs vereist.
DPoP-token (sender-constrained)
Het token is gekoppeld aan een sleutelpaar. Elke aanvraag vereist een verse ondertekende proof. Gestolen tokens zijn waardeloos zonder de private sleutel.

Hoe DPoP werkt

De DPoP-flow voegt een lichte cryptografische stap toe aan het standaard OAuth2-proces:

1. Sleutelgeneratie — De client genereert een asymmetrisch sleutelpaar (ES256 of RS256). De private key blijft op de client; de public key wordt als JWK opgenomen in DPoP-proofs.

2. Tokenaanvraag — Bij het aanvragen van een access token voegt de client een DPoP-HTTP-header toe met een ondertekende JWT-proof. De proof bevat de HTTP-methode, URL, timestamp en een unieke identifier.

3. Tokenbinding — De authorization server verifieert de proof-handtekening, haalt de JWK-thumbprint op (SHA-256-hash van de public key) en koppelt deze aan het uitgegeven token. Het antwoord bevat token_type: DPoP in plaats van Bearer.

4. Resource-toegang — Bij elke API-aanroep stuurt de client zowel het token als een verse DPoP-proof. De proof bevat een ath-claim (SHA-256-hash van het access token), waardoor de proof aan dat specifieke token wordt gekoppeld.

Binnenkant van een DPoP-proof

Een DPoP-proof is een compacte JWT met drie delen: header, payload en handtekening.

// Header - identificeert de sleutel en het algoritme
{
  "typ": "dpop+jwt",
  "alg": "ES256",
  "jwk": {
    "kty": "EC",
    "crv": "P-256",
    "x": "cWs37kZLJMej6fpd...",
    "y": "e2bkcQGaBERgSZUb..."
  }
}
// Payload - bewijst de versheid en koppelt aan het verzoek
{
  "htm": "POST",
  "htu": "https://auth.example.com/oauth/token",
  "iat": 1774950263,
  "jti": "F1AFCD1F-95F7-401B-A2F5-195A31DB1802",
  "ath": "fUHyO2r2Z3DZ53EsNr..."
}

DPoP configureren in sgcWebSockets

Stap 1: genereer een ES256-sleutelpaar

Gebruik OpenSSL om een elliptic-curve-sleutelpaar te genereren:

# EC-private-sleutel genereren
openssl ecparam -name prime256v1 -genkey -noout -out dpop_private.pem
# Public-key-parameters extraheren
openssl ec -in dpop_private.pem -text -noout

Zet de X- en Y-coördinaten van de public key om naar Base64URL om de JWK op te bouwen:

{"kty":"EC","crv":"P-256","x":"cWs37kZLJMej6fpdyKaI8Gz6CE...","y":"e2bkcQGaBERgSZUbAGR-iOOM..."}

Stap 2: configureer de OAuth2-client

// OAuth2 configureren zoals gebruikelijk
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';
// DPoP inschakelen
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":"..."}';
// De OAuth2-flow starten - DPoP-headers worden automatisch toegevoegd
OAuth2.Start;

Dat is alles. De component doet automatisch het volgende:

Stap 3: gebruik DPoP-proofs voor API-aanroepen

Nadat je een DPoP-gebonden access token hebt verkregen, genereer je een proof voor elke API-aanvraag:

var
  vProof: String;
begin
  // Een DPoP-proof genereren voor de API-aanroep
  vProof := OAuth2.GetDPoPProof(
    'GET',
    'https://api.example.com/userinfo',
    OAuth2.AccessToken
  );
  // Voeg beide headers toe aan je 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;

Ondersteunde providers

DPoP wordt al ondersteund door grote OAuth2-providers:

Auth0 Schakel DPoP in via de applicatie-instellingen. Vereist nonce-ondersteuning (wordt automatisch afgehandeld).
Okta Configureer DPoP in de access-policies van de authorization server. Algemeen beschikbaar sinds 2024.
Microsoft Entra ID Ondersteunt DPoP voor confidential clients.
Ping Identity Volledige DPoP-ondersteuning in PingOne en PingFederate.

DPoP-validatie aan serverzijde

De OAuth2-servercomponent van sgcWebSockets ondersteunt ook DPoP-validatie. Wanneer OAuth2Options.DPoP is ingeschakeld, doet de server automatisch het volgende:

// DPoP inschakelen op de OAuth2-server
OAuth2Server.OAuth2Options.DPoP := True;
// Optioneel: aangepaste validatie via event
OAuth2Server.OnOAuth2ValidateDPoP := procedure(Sender: TObject;
  Connection: TsgcWSConnection;
  const DPoPProof, AccessToken: String;
  var IsValid: Boolean)
begin
  // Voeg hier aangepaste checks toe (bijvoorbeeld validatie tegen een sleutelregister)
  IsValid := True;
end;

DPoP-API-referentie

Property / methode Beschrijving
DPoPOptions.Enabled Schakelt DPoP in voor alle token-aanvragen.
DPoPOptions.Algorithm dpopES256 (aanbevolen) of dpopRS256.
DPoPOptions.PrivateKey PEM-gecodeerde private sleutel voor het ondertekenen van DPoP-proofs.
DPoPOptions.PublicKeyJWK JSON Web Key-representatie van de public key.
GetDPoPProof() Genereert een DPoP-proof-JWT voor een specifieke HTTP-methode, URL en access token.
GetDPoPJWKThumbprint() Geeft de RFC 7638 SHA-256-thumbprint van de public key terug.
DPoPNonce De huidige DPoP-Nonce-waarde van de server (alleen-lezen).

Upgrade je tokenbeveiliging

DPoP is de meest significante verbetering van de tokenbeveiliging in OAuth 2.0 sinds PKCE. Het elimineert de hele categorie van tokendiefstal-aanvallen met minimale codewijzigingen — zet gewoon DPoPOptions.Enabled := True, geef je sleutels op en de sgcWebSockets-component regelt de rest.

DPoP-ondersteuning is beschikbaar in sgcWebSockets 2026.4.0 voor zowel Delphi (DXE6 tot en met D13) als .NET (.NET Framework 2.0 tot en met .NET 9). Download de nieuwste versie op esegece.com.