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:
- Genereert een verse DPoP-proof-JWT voor elke tokenaanvraag
- Handelt
DPoP-Nonce-server-challenges en retries transparant af - Slaat de nonce op voor volgende aanvragen
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:
- Valideert DPoP-proof-JWT's (handtekening, claims, freshness)
- Koppelt tokens aan de JWK-thumbprint van de client
- Geeft
token_type: DPoPterug voor DPoP-gebonden tokens - Weigert aanvragen met ongeldige of ontbrekende proofs (geeft 400
invalid_dpop_proofterug) - Verifieert de
ath-claim (hash van het access token) bij resource-aanvragen
// 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.
