After a user completes a second factor (TOTP today; passkey assertion can wire to the same surface), the client can ask Pylon to remember this browser so the second factor is skipped for 30 days on this device. The trust is bound to the user — a stale cookie from a previous account on the same browser quietly degrades to untrusted, never elevates a different user. The trust flows throughDocumentation Index
Fetch the complete documentation index at: https://docs.pylonsync.com/llms.txt
Use this file to discover all available pages before exploring further.
auth.isTrustedDevice so policies can gate sensitive flows on it (“require fresh TOTP unless trusted device”).
Endpoints
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/api/auth/trusted-devices | GET | session | List the user’s trusted browsers |
/api/auth/trusted-devices | DELETE | session | Revoke ALL of the user’s trusted devices |
/api/auth/trusted-devices/:id | DELETE | session | Revoke one trusted device |
403 API_KEY_AUTH_FORBIDDEN.
Minting trust
There’s no dedicated “trust this device” endpoint. Trust is minted as a side effect of a successful second-factor verify, on opt-in:trust_device: true is set on /totp/verify, Pylon:
- Mints a 256-bit random trust token.
- Persists a
TrustedDevicerecord bound to the user. - Sets a
pylon_trusted_devicecookie (HttpOnly,SameSite=Lax,Securein non-dev) with a 30-day lifetime.
trust_device: true to confirm:
record.user_id == session.user_id on every request.
Listing devices
label is parsed from the request’s User-Agent header at mint time. Browsers display it in the “active devices” account settings page.
Revoking
Revoke one device by id:user_id matches the caller. Cross-user revoke attempts return 404 NOT_FOUND — identical to “device doesn’t exist” — so a curious admin can’t enumerate trust-device ids via response timing.
Revoke all devices (the “log everything else out of TOTP” button):
revoked: <count> of records removed. The current request’s trust cookie is also cleared via Set-Cookie on the response so the browser drops it immediately.
Gating in your policies / handlers
The trust flag rides onAuthContext.is_trusted_device. Use it in TS handlers:
auth.isTrustedDevice (bool). Combine with role checks to gate sensitive entity reads/writes.
Lifetime + cookie attributes
- Lifetime: 30 days from mint (
DEFAULT_TRUST_LIFETIME_SECS = 30 * 24 * 60 * 60). - Cookie name:
pylon_trusted_device. - Attributes: built from the framework’s existing
CookieConfig— sameSecure/SameSite/Pathas the session cookie. Operators don’t have to configure two sets.
Security guarantees
- Token stays server-side. Listing trusted devices returns the
id(public handle) but never the cookie value. XSS that reaches/trusted-devicescan’t exfiltrate trust tokens; it would have to readdocument.cookie(HttpOnly defends). - Bound to user. Every verify checks
record.user_id == session.user_id. Stealing the cookie alone doesn’t help — you need both the trust cookie and the matching session. - Object-level auth on revoke with timing parity — cross-user revoke attempts and “doesn’t exist” return the same
404from the same code path. - Auto-cleared on full revoke.
DELETE /trusted-devices(all) wipes the cookie on the response so the browser drops it without a refresh. - HttpOnly + Secure + SameSite=Lax — same posture as the session cookie.
Where to go next
- TOTP / 2FA — the verify endpoint that mints trust via
trust_device: true - Sessions — base cookie attribute config that trusted-device cookies inherit
- Passkeys — phishing-resistant alternative; usually you DON’T need a remember-device gate when the user uses a passkey