OAuth 2.0-Access-Tokens sind die Schlüssel zu deinem API-Königreich — und wenn jemand einen stiehlt, kann er ihn von überall aus verwenden. DPoP (Demonstrating Proof of Possession), definiert in RFC 9449, löst dieses Problem, indem Tokens kryptografisch an den Client gebunden werden, der sie angefordert hat. Selbst wenn ein Token abgefangen wird, ist es ohne den privaten Schlüssel des Clients nutzlos.
Ab sgcWebSockets 2026.4.0 bieten die OAuth2-Client- und Server-Komponenten volle DPoP-Unterstützung. Dieser Artikel erklärt, was DPoP ist, wie es funktioniert und wie du es in deiner Delphi-Anwendung konfigurierst.
Was ist DPoP?
In Standard-OAuth 2.0 funktioniert ein Bearer-Token wie Bargeld — wer es hat, kann es ausgeben. Fängt ein Angreifer das Token über ein kompromittiertes Netzwerk, geleakte Logs oder einen bösartigen Proxy ab, hat er vollen Zugriff auf deine geschützten Ressourcen.
DPoP ändert das, indem es Tokens wie eine Kreditkarte mit PIN funktionieren lässt. Das Token selbst ist an einen öffentlichen Schlüssel gebunden, und jede Anfrage muss ein Proof-JWT enthalten, das mit dem entsprechenden privaten Schlüssel signiert ist. Der Server überprüft, ob der Proof zum gebundenen Schlüssel passt, bevor er die Anfrage akzeptiert.
|
Bearer Token (traditionell) Jeder, der das Token besitzt, kann es nutzen. Gestohlene Tokens sind voll ausnutzbar. Kein Identitätsnachweis erforderlich. |
DPoP Token (Sender-gebunden) Token ist an ein Schlüsselpaar gebunden. Jede Anfrage erfordert einen frischen signierten Proof. Gestohlene Tokens sind ohne den privaten Schlüssel wertlos. |
Wie DPoP funktioniert
Der DPoP-Flow fügt dem Standard-OAuth2-Prozess einen leichtgewichtigen kryptografischen Schritt hinzu:
1. Schlüsselerzeugung — Der Client erzeugt ein asymmetrisches Schlüsselpaar (ES256 oder RS256). Der private Schlüssel verbleibt beim Client; der öffentliche Schlüssel wird als JWK in DPoP-Proofs eingebettet.
2. Token-Anfrage — Beim Anfordern eines Access-Tokens fügt der Client einen DPoP-HTTP-Header mit einem signierten JWT-Proof hinzu. Der Proof enthält die HTTP-Methode, URL, einen Zeitstempel und einen eindeutigen Identifier.
3. Token-Bindung — Der Authorization Server überprüft die Proof-Signatur, extrahiert den JWK-Thumbprint (SHA-256-Hash des öffentlichen Schlüssels) und bindet ihn an das ausgegebene Token. Die Antwort enthält token_type: DPoP statt Bearer.
4. Ressourcenzugriff — Bei jedem API-Aufruf sendet der Client sowohl das Token als auch einen frischen DPoP-Proof. Der Proof enthält einen ath-Claim (SHA-256-Hash des Access-Tokens), der den Proof an genau dieses Token bindet.
Innerhalb eines DPoP-Proofs
Ein DPoP-Proof ist ein kompaktes JWT mit drei Teilen: Header, Payload und Signatur.
// 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..."
}
DPoP in sgcWebSockets konfigurieren
Schritt 1: Ein ES256-Schlüsselpaar erzeugen
Verwende OpenSSL, um ein Elliptic-Curve-Schlüsselpaar zu erzeugen:
# 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
Konvertiere die X- und Y-Koordinaten des öffentlichen Schlüssels nach Base64URL, um das JWK zu erstellen:
{"kty":"EC","crv":"P-256","x":"cWs37kZLJMej6fpdyKaI8Gz6CE...","y":"e2bkcQGaBERgSZUbAGR-iOOM..."}
Schritt 2: Den OAuth2-Client konfigurieren
// 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;
Das war's. Die Komponente erledigt automatisch:
- Sie erzeugt für jede Token-Anfrage einen frischen DPoP-Proof-JWT
- Sie verarbeitet
DPoP-Nonce-Server-Challenges und Wiederholungen transparent - Sie speichert die Nonce für nachfolgende Anfragen
Schritt 3: DPoP-Proofs für API-Aufrufe verwenden
Nachdem du ein DPoP-gebundenes Access-Token erhalten hast, erzeuge für jede API-Anfrage einen Proof:
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;
Unterstützte Anbieter
DPoP wird bereits von den wichtigsten OAuth2-Anbietern unterstützt:
| Auth0 | Aktiviere DPoP in den Anwendungseinstellungen. Benötigt Nonce-Unterstützung (wird automatisch verarbeitet). |
| Okta | Konfiguriere DPoP in den Access Policies des Authorization Servers. Seit 2024 allgemein verfügbar. |
| Microsoft Entra ID | Unterstützt DPoP für vertrauliche Clients. |
| Ping Identity | Volle DPoP-Unterstützung in PingOne und PingFederate. |
Serverseitige DPoP-Validierung
Die sgcWebSockets OAuth2-Server-Komponente unterstützt auch die DPoP-Validierung. Wenn OAuth2Options.DPoP aktiviert ist, erledigt der Server automatisch:
- Validierung von DPoP-Proof-JWTs (Signatur, Claims, Frische)
- Bindet Tokens an den JWK-Thumbprint des Clients
- Gibt
token_type: DPoPfür DPoP-gebundene Tokens zurück - Lehnt Anfragen mit ungültigen oder fehlenden Proofs ab (gibt 400
invalid_dpop_proofzurück) - Verifiziert den
ath-Claim (Access-Token-Hash) bei Ressourcenanfragen
// 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;
DPoP API-Referenz
| Eigenschaft / Methode | Beschreibung |
|---|---|
DPoPOptions.Enabled |
Aktiviert DPoP für alle Token-Anfragen. |
DPoPOptions.Algorithm |
dpopES256 (empfohlen) oder dpopRS256. |
DPoPOptions.PrivateKey |
PEM-kodierter privater Schlüssel zum Signieren von DPoP-Proofs. |
DPoPOptions.PublicKeyJWK |
JSON Web Key-Darstellung des öffentlichen Schlüssels. |
GetDPoPProof() |
Erzeugt einen DPoP-Proof-JWT für eine bestimmte HTTP-Methode, URL und ein Access-Token. |
GetDPoPJWKThumbprint() |
Gibt den RFC 7638 SHA-256-Thumbprint des öffentlichen Schlüssels zurück. |
DPoPNonce |
Der aktuelle DPoP-Nonce-Wert vom Server (schreibgeschützt). |
Verbessere deine Token-Sicherheit
DPoP ist die bedeutendste Verbesserung der OAuth 2.0-Token-Sicherheit seit PKCE. Es eliminiert die gesamte Klasse von Token-Diebstahl-Angriffen mit minimalen Codeänderungen — setze einfach DPoPOptions.Enabled := True, gib deine Schlüssel an, und die sgcWebSockets-Komponente erledigt den Rest.
DPoP-Unterstützung ist verfügbar in sgcWebSockets 2026.4.0 für Delphi (DXE6 bis D13) und .NET (.NET Framework 2.0 bis .NET 9). Lade die aktuellste Version unter esegece.com herunter.
