Summary
Sessions are not bound to any device characteristics. A stolen JWT token can be used from any device, location, or browser. There is no device fingerprinting, no session pinning, and no way to detect when a token is being used from an unexpected environment.
Recommendation
Device Fingerprinting
Collect a browser fingerprint on auth and bind it to the session:
- Canvas/WebGL fingerprint hash
- Screen resolution, color depth, timezone
- Installed fonts (subset)
- Navigator properties (platform, language, hardwareConcurrency)
- Audio context fingerprint
Use a library like FingerprintJS (open-source core) or build a lightweight custom fingerprint.
Session Binding
- On login, compute device fingerprint and send with auth request
- Auth service stores fingerprint hash alongside session
- On subsequent requests, client sends fingerprint in a header (e.g.,
X-Device-Fingerprint)
- Backend compares against stored fingerprint — mismatch triggers re-auth or rejection
Headless Browser Detection
Add client-side checks for automation indicators:
const isHeadless = (
navigator.webdriver ||
!window.chrome ||
/HeadlessChrome/.test(navigator.userAgent) ||
window.outerHeight === 0 ||
navigator.plugins.length === 0
);
Bot Indicators to Track
navigator.webdriver === true (Selenium, Puppeteer)
- Missing
window.chrome object in Chrome
HeadlessChrome in user-agent
- Zero plugins/mimeTypes
- Phantom/unusual screen dimensions (0x0, 800x600 headless defaults)
- Missing WebGL renderer info
- Consistent fingerprint across many "different" accounts (bot farm)
Impact
- Prevents token replay from different devices
- Detects headless browser automation
- Identifies bot farms reusing the same fingerprint across accounts
- Raises the cost of credential stuffing attacks
Summary
Sessions are not bound to any device characteristics. A stolen JWT token can be used from any device, location, or browser. There is no device fingerprinting, no session pinning, and no way to detect when a token is being used from an unexpected environment.
Recommendation
Device Fingerprinting
Collect a browser fingerprint on auth and bind it to the session:
Use a library like FingerprintJS (open-source core) or build a lightweight custom fingerprint.
Session Binding
X-Device-Fingerprint)Headless Browser Detection
Add client-side checks for automation indicators:
Bot Indicators to Track
navigator.webdriver=== true (Selenium, Puppeteer)window.chromeobject in ChromeHeadlessChromein user-agentImpact