Implementing Token Binding
1. Understanding Token Binding Concepts
| Concept | Detail |
|---|---|
| Goal | Tie token to client cryptographic key — stolen token unusable elsewhere |
| Mechanism | Token includes cnf claim referencing public key / cert |
| Proof | Client signs request or completes TLS handshake with bound key |
| Specs | RFC 8473 (TLS), RFC 7800 (cnf), DPoP (RFC 9449) |
2. Implementing Proof-of-Possession Tokens
Example: DPoP header (RFC 9449)
// Client signs a JWT with its private key per request
const dpopProof = await new SignJWT({
htu: "https://api.example.com/orders",
htm: "GET",
jti: crypto.randomUUID(),
iat: Math.floor(Date.now()/1000)
})
.setProtectedHeader({ alg: "ES256", typ: "dpop+jwt", jwk: publicJwk })
.sign(privateKey);
fetch("/orders", {
headers: {
"Authorization": "DPoP " + accessToken,
"DPoP": dpopProof
}
});
3. Using TLS Token Binding
| Aspect | Detail |
|---|---|
| Spec | RFC 8471/8472/8473 LIMITED |
| Status | Chrome removed support; DPoP/mTLS preferred today |
| Replacement | DPoP, mTLS-bound tokens (RFC 8705) |
4. Preventing Token Theft
| Layer | Defense |
|---|---|
| Storage | HttpOnly cookies, OS secure storage |
| Transport | HTTPS + HSTS + cert pinning |
| Binding | DPoP, mTLS-bound tokens |
| Detection | Anomaly detection (IP/device changes) |
| Lifetime | Short-lived access tokens |
5. Implementing Device-Bound Tokens
| Approach | Detail |
|---|---|
| Device key | Generated in TPM / Secure Enclave |
| Attestation | WebAuthn / Android Key Attestation proves key non-exportable |
| Token claim | cnf: { "jkt": "<thumbprint>" } |
| DBSC NEW | Device Bound Session Credentials (Chrome experimental) |
6. Using Channel Binding
| Binding Type | Detail |
|---|---|
| tls-server-end-point | Hash of TLS server cert |
| tls-unique | TLS Finished message |
| tls-exporter | RFC 9266, modern replacement for tls-unique |
| Use | SASL, SCRAM, Kerberos GSS-API |
7. Implementing Token Binding in OAuth
| Method | Spec | Status (2026) |
|---|---|---|
| mTLS-bound tokens | RFC 8705 | Enterprise, FAPI |
| DPoP | RFC 9449 | Recommended for SPAs/mobile |
| PoP keys | RFC 7800 (cnf) | Underlying mechanism |
8. Validating Token Binding
| Step | Action |
|---|---|
| 1 | Extract cnf claim (e.g., jkt thumbprint) |
| 2 | Read presented key (DPoP JWK, mTLS cert) |
| 3 | Compute SHA-256 thumbprint, compare constant-time |
| 4 | Verify proof signature over htu/htm/iat/jti |
| 5 | Check jti freshness (anti-replay window) |
9. Handling Token Binding Errors
| Error | Cause |
|---|---|
| invalid_dpop_proof | Bad signature or wrong htu/htm |
| use_dpop_nonce | Server requires nonce — retry with provided nonce |
| invalid_token | jkt thumbprint mismatch |
| Replay detected | jti seen recently → reject |
10. Understanding Token Binding vs Certificate Pinning
| Aspect | Token Binding | Cert Pinning |
|---|---|---|
| Binds | Token to client key | Client trust to server cert |
| Layer | Application (OAuth) | Transport (TLS) |
| Protects against | Token theft / replay | MitM, rogue CAs |
| Where used | API auth | Mobile / IoT clients |