Token Binding — Binding Tokens to Client Devices for Security
DodaTech
Updated 2026-06-28
1 min read
In this tutorial, you'll learn about Token Binding. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Token binding cryptographically binds authentication tokens to a specific client, making stolen tokens unusable from other devices.
// DPoP (Demonstrating Proof of Possession) implementation
class DPoPProof {
constructor(privateKey) {
this.privateKey = privateKey;
}
async generateProof(method, url, accessToken) {
const header = {
typ: 'dpop+jwt',
alg: 'ES256',
jwk: await this.getPublicJWK()
};
const thumbprint = await this.calculateJWKThumbprint(header.jwk);
const payload = {
jti: crypto.randomUUID(),
htm: method,
htu: url,
iat: Math.floor(Date.now() / 1000),
ath: await this.hashAccessToken(accessToken)
};
return this.sign(header, payload);
}
async hashAccessToken(token) {
const hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(token));
return base64url(new Uint8Array(hash));
}
async calculateJWKThumbprint(jwk) {
const sorted = {
crv: jwk.crv,
kty: jwk.kty,
x: jwk.x,
y: jwk.y
};
const hash = await crypto.subtle.digest('SHA-256',
new TextEncoder().encode(JSON.stringify(sorted)));
return base64url(new Uint8Array(hash));
}
async sign(header, payload) {
const encoder = new TextEncoder();
const data = encoder.encode(
`${base64url(encoder.encode(JSON.stringify(header)))}.${base64url(encoder.encode(JSON.stringify(payload)))}`
);
const signature = await crypto.subtle.sign(
{ name: 'ECDSA', hash: 'SHA-256' },
this.privateKey,
data
);
return `${base64url(encoder.encode(JSON.stringify(header)))}.${base64url(encoder.encode(JSON.stringify(payload)))}.${base64url(new Uint8Array(signature))}`;
}
}
// DPoP validation middleware
async function validateDPoP(req, res, next) {
const authHeader = req.headers.authorization;
const dpopHeader = req.headers['dpop'];
if (!authHeader || !dpopHeader) return res.status(401).json({ error: 'DPoP required' });
const token = authHeader.slice(7);
const dpopParts = dpopHeader.split('.');
// Validate DPoP proof
const dpopHeader_decoded = JSON.parse(atob(dpopParts[0]));
const dpopPayload_decoded = JSON.parse(atob(dpopParts[1]));
// Verify HTTP method and URL match
if (dpopPayload_decoded.htm !== req.method) return res.status(401).json({ error: 'Method mismatch' });
if (dpopPayload_decoded.htu !== `${req.protocol}://${req.get('host')}${req.originalUrl}`) {
return res.status(401).json({ error: 'URL mismatch' });
}
// Verify token hash
const tokenHash = await hashAccessToken(token);
if (dpopPayload_decoded.ath !== tokenHash) {
return res.status(401).json({ error: 'Token hash mismatch' });
}
// Verify signature against JWK in header
// ... signature verification logic
next();
}
Token binding prevents token theft by making tokens cryptographically bound to the intended client.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro