Core Concepts
How Access Token, Refresh ID, device binding, transparent refresh, and revocation work together.
Token pair
| Token | Storage | Lifetime (default) | Role |
|---|---|---|---|
| Access Token | Cookie access_token or Authorization: Bearer |
15 minutes | Short-lived ES256 JWT carrying user claims |
| Refresh ID | Cookie refresh_id or header X-Refresh-ID |
7 days | Opaque session key in Redis (refresh:{id}) |
Create signs the Access Token, generates a Refresh ID, writes both cookies, and stores RefreshData plus a JTI key in Redis via a transaction pipeline.
Device fingerprint
Each session is bound to a fingerprint derived from OS, browser, and device ID (SHA-256). On verify and refresh the library recomputes the fingerprint and rejects mismatches so a stolen token cannot be reused on another device.
Optional request headers:
| Header | Purpose |
|---|---|
X-Device-FP |
Override computed fingerprint |
X-Device-ID |
Stable device identifier used in fingerprint input |
Transparent refresh
When Verify finds a missing or expired Access Token but a valid Refresh ID:
- Acquire a distributed lock (
lock:refresh:{id}) with SetNX. - Load
RefreshDatafrom Redis and re-check fingerprint. - Optionally call
CheckAuthto ensure the user still exists. - Re-sign Access Token; if
VersionexceedsMaxVersionor remaining TTL ratio falls belowRefreshTTL, fully rotate the Refresh ID. - Update Redis keys and set response headers
X-New-Access-Token/X-New-Refresh-IDwhen values change.
Revocation
Revoke clears cookies, shortens the Refresh ID TTL, and writes revoke:{accessToken} so subsequent verifies fail with errorRevoked even if the JWT has not expired yet.
Middleware context
| Framework | Middleware | Read helper | Context key |
|---|---|---|---|
| Gin | GinMiddleware() |
GetAuthDataFromGinContext |
user |
| net/http | HTTPMiddleware(next) |
GetAuthDataFromHTTPRequest |
user in request.Context |
On failure both middlewares return JSON {"error": ...} with the status from JWTAuthResult.
Redis keys
| Pattern | Meaning |
|---|---|
refresh:%s |
Serialized RefreshData for a Refresh ID |
jti:%s |
Active Access Token JTI marker |
lock:refresh:%s |
Distributed lock during refresh |
revoke:%s |
Revoked Access Token marker |
Import path
Library sources live under core/ with package name goJwt:
import goJwt "github.com/pardnchiu/go-jwt/core"