Device Fingerprint

Last updated

This page explains how the device fingerprint that tokens are bound to is generated, where it is checked, and how detection actually behaves.

Generation

CreateFingerprint() (src/CreateFingerprint.ts) builds a JSON object from these four values and takes its SHA-256 hex digest:

Field Source
os User-Agent match
browser User-Agent match
device User-Agent match
deviceId X-Device-ID header → req.body.deviceId → "Unknown"

When req.session.fp exists (for example, stored yourself with express-session), every API uses it instead of recomputing.

Detection Rules

Matching runs top to bottom and the first hit wins:

Field Order
os Windows → Macintosh|Mac OS X → Linux → Android → iPhone|iPad|iPod → Unknown_OS
browser Edge|Edg → Firefox → Chrome → Safari → Opera|OPR → Unknown_Browser
device iPad → iPhone|iPod|Android.*Mobile|BlackBerry|IEMobile|Opera Mini → Desktop

Because matching stops at the first hit, some results are counterintuitive:

User-Agent Actual result Why
Android os: Linux Android UAs contain Linux, which is checked before Android
iPhone / iPad os: MacOS iOS UAs contain like Mac OS X
Opera browser: Chrome Opera UAs contain Chrome

These values only feed the hash; binding works as long as the same device produces the same result each time.

Where It Is Checked

When Result on mismatch
fp in a valid Access Token isError: true
fp decoded from an expired Access Token isError: true
fp in Redis refresh data isError: false (guest)

Related: Token Transport, Client Integration

中文