Session integrity
Every device is known and revocable
A stolen laptop, a forgotten phone in a taxi, a contractor whose access ended last week — every one of these is a session that must die at the moment we say it does. We treat device and session state as a first-class auditable boundary, not a side effect of cookies.
Executive summary
Every login is fingerprinted at a 128-bit truncated SHA-256 of source IP and user agent, tied to a session token that is itself stored as a hash. Even with a database dump, an attacker cannot replay an active session.
A new-device login fires a security event the user can see and revoke from any other session. "Log out everywhere" kills every active session in one transaction; revoked tokens close LiveView sockets in real time.
Our commitments
Five rules for the session boundary
The session boundary is the perimeter of every other security control. We hold it tightly.
Session tokens are hashed at rest
Even with full database read access, an attacker cannot impersonate an active session. The raw token only ever lives in the user's cookie.
Every new device produces an audit event
A login from an unrecognized fingerprint generates a :login_new_device event the user can review and act on — including from another session in real time.
Revocation is instant and audit-preserved
Revoking a device or session deletes the token but writes an immutable security event with the actor, time, and reason.
Sealing requires MFA, every time
Even a fully trusted device on a healthy session must re-prove identity before applying a professional seal. The seal is the moment that matters.
Trust is opt-in, never inferred
A device is 'known' the first time it logs in successfully. It only becomes 'trusted' when the user explicitly marks it. We never auto-elevate trust.
Implementation — device fingerprinting
How we identify a device
The fingerprint is a stable session-scoped hash, not a tracker. We do not collect MAC addresses, IMEIs, or hardware serials.
Implementation — session tokens
How sessions are stored and revoked
The full picture
What is built, what is being built, and what we chose not to build
Live today
SHA-256 device fingerprinting with race-safe upsert
LiveConcurrent logins from a new device cannot create duplicates; unique constraint on (user_id, device_fingerprint).
New-device security events
LiveA :login_new_device event fires exactly once per fingerprint, with IP and user agent metadata for review.
Hashed session tokens with double-hash for sync
LiveAt rest: SHA-256(raw). Over Phoenix Sync streams: SHA-256(SHA-256(raw)). The client cannot reconstruct a usable token from any leak surface.
Log out everywhere / log out other devices
LiveSingle-transaction bulk revocation; LiveView sockets close in real time as their tokens are killed.
Step-up MFA at sealing (10-minute sudo window)
LiveMFA enrollment is required before a user can seal. The first seal in a session prompts a fresh TOTP (or one-time backup code); subsequent seals within a 10-minute window pass through. The same gate applies to single-doc and batch seals — one verification authorizes the batch. Every gate outcome (blocked, failed, passed) is recorded in the hash-chained audit log.
Geolocation enrichment of login events
LiveEach session's source IP is geolocated; sudden country changes surface in the security event log.
Per-org max concurrent session policy
LiveOrg admins can cap how many simultaneous sessions a single user may hold; enforced at login.
Building now
WebAuthn / FIDO2 passkeys
Building nowDevice-bound public-key authentication that replaces TOTP for sealing. Phishing-resistant, no shared secret to steal.
Target: passkey enrollment in settings this quarter; sealing-gate integration next.
Step-up authentication for sensitive operations
Building nowRe-prompt for MFA or passkey on credential changes, payment method updates, and member-role escalation — not just on sealing.
Impossible-travel detection
Building nowFlag sessions whose source location moved faster than a commercial flight could explain. Triggers a forced re-auth instead of a hard kick.
Roadmap
Hardware key requirement (Enterprise policy)
RoadmapOrg admins can require a FIDO2 hardware key for any sealing operation, optionally limiting which key vendors are accepted.
Driven by Enterprise customers with existing hardware-key fleets.
Device attestation
RoadmapVerify a managed device's identity (TPM-backed key on Windows, Secure Enclave on Apple) before granting access.
Continuous session re-evaluation
RoadmapPeriodic background re-checks of session posture (geo, risk score, device trust); inactive sessions auto-tier down.
Session export for SIEM ingestion
RoadmapPush login and session events to your SIEM (Splunk, Datadog, Sumo) over a signed webhook stream.
Considered & rejected
Browser-fingerprint tracking (canvas, fonts, WebGL)
Considered & rejectedA SHA-256 of IP + UA is a session-scoped identifier the user can break by clearing cookies. We do not want to know more than that.
Why we rejected it: high-entropy fingerprints cross the line from "is this the same session" to "is this the same person across browsers and incognito." That is tracking, not security. We are a sealing platform; we do not need it.
MAC address / IMEI / hardware serial as device ID
Considered & rejectedThese cannot be revoked, often cannot be rotated, and survive factory resets. A leaked IMEI is forever.
Why we rejected it: hardware identifiers are an attractive nuisance. They look stable, but they create a permanent record that follows the user forever and creates HIPAA / GDPR risk we do not need.
SMS-based MFA
Considered & rejectedSS7 attacks, SIM swapping, and carrier-side inspection make SMS the weakest second factor in common use.
Why we rejected it: SMS is broken for security, full stop. NIST has been deprecating SMS-as-second-factor since 2016. We use TOTP today and are moving to passkeys; SMS is not on the path.
Aggressive geofencing as a hard block
Considered & rejectedA licensed engineer in Texas legitimately travels to a conference in Germany. Hard-blocking on country mismatch generates more support tickets than security wins.
Why we rejected it: we surface geo signals (impossible-travel, sudden country change) but trigger step-up auth, not termination. False positives in security have a cost — we measure it and design around it.
Persistent "remember this device for 90 days" MFA bypass
Considered & rejectedLong-lived MFA bypasses are the most common path to account takeover. We do not offer them, even though competitors do.
Why we rejected it: every "remember me" is a prefilled answer to "did you actually verify the human?" For sealing — a legally significant act — we accept the friction of MFA every time. The friction is the feature.
Compliance mappings
Controls this surface satisfies
Logical Access — Authentication
Session MFA; hashed session tokens; bound device fingerprints
Logical Access — User Access Management
Per-user device list with explicit trust + revoke surfaces
Logical Access — Termination
Single-transaction bulk session revocation; instant socket teardown
System Operations — Anomaly Detection
New-device events, geolocation enrichment, impossible-travel signals
Removal or adjustment of access rights
Audit-preserved soft-delete on devices and sessions
Secure log-on procedures
MFA, session token hashing, fingerprint-based new-device alerts
Automatic Logoff
Per-org max-session policy; idle session expiry configurable
Authentication Assurance Level 2
TOTP today; passkeys (AAL3-eligible) shipping this quarter
For compliance teams
Questions you don't need to call to ask
What's the maximum session lifetime?
What happens to a user's sessions when they're removed from an org?
Can a contractor's access be time-bounded?
How do you handle stolen-laptop scenarios?
Do you support hardware security keys?
What about impossible-travel detection?
Where can I see every device + session for my organization?
Is the session activity log immutable?
Credo.Security.Event.record/3
— MFA challenges (passed, failed, enrolled), SCIM-driven user lifecycle, and step-up MFA at sealing (blocked, passed, failed) — are mirrored row-for-row into the per-organization hash-chained
audit_logs
table that also holds the seal events. Tampering with any mirrored record invalidates every record after it on the per-org chain; the chain is independently verifiable via
Credo.Enterprise.Audit.AuditChain. See the
audit chain page
for the mirror semantics and best-effort failure mode.
Trust the device, prove the human, log everything
Three commitments, one consistent surface. Talk to our team about org-specific session policies.