Skip to main content
ConnectFor teamsSign inDashboard
Security · Defense in depth

One breach, five layers still standing.

Six layers of defense. Each one blocks threats on its own. From the sign-in flow to the audit log, if one layer is breached, the other five still hold.

01Protocol

The sign-in flow is the first gate.

We require theft-protection (PKCE) on the sign-in authorization flow. Authorization requests are pre-registered on the server (PAR), and issued tokens are cryptographically bound to the device (DPoP).

OIDC CorePKCE S256PAR RFC 9126DPoP RFC 9449
Layer 01 / 06
protocol.ts
// PKCE S256 challenge
const verifier = crypto.randomUUID();
const challenge = base64url(
  await crypto.subtle.digest("SHA-256", encode(verifier))
);
02Password

Verification beyond the password.

Passwords are securely hashed (bcrypt) and checked against the global breached-password database (HIBP) in real time on every sign-in. Automatic lockout on repeated failures blocks brute-force attacks.

bcryptHIBP APIAccount Lockout
Layer 02 / 06
password.ts
// HIBP breach check on sign-in
const hash = sha1(password).slice(0, 5);
const breached = await hibp.check(hash);
if (breached) throw new BreachedPasswordError();
03Token

A stolen token still can't be used.

Access tokens are signed so they can't be forged (ES256). Refresh tokens are replaced on every use and bound to the device they were issued to (DPoP).

ES256 JWTRefresh RotationDPoP BindingRFC 7519
Layer 03 / 06
token.ts
// DPoP-bound token verification
const { payload } = await jwtVerify(token, publicKey);
const dpopProof = request.headers.get("DPoP");
verifyDPoPBinding(payload.cnf, dpopProof);
04Session

Sessions are tied to the device.

Each session is bound to a device fingerprint. Idle expiry (7 days) and maximum lifetime are managed separately.

Device FingerprintSession BindingAMR RFC 8176
Layer 04 / 06
session.ts
// Device fingerprint validation
const fp = generateFingerprint(request);
if (session.deviceFp !== fp) {
  await revokeSession(session.id);
  throw new SessionHijackError();
}
05Network

Block at the network edge.

Precise, database-backed request-rate limiting. IP policies (allow/deny ranges), domain-origin restrictions, and per-organization real-time origin checks.

Rate LimitingIP PolicyCORSCSP
Layer 05 / 06
network.ts
// Atomic rate limit check (D1 batch)
const [insert, count] = await db.batch([
  db.prepare("INSERT INTO rate_limit ..."),
  db.prepare("SELECT COUNT(*) ...")
]);
if (count > threshold) throw new RateLimitError();
06Audit

Every action is logged.

We record 55 kinds of events and deliver them by webhook. Real-time security signals (SSF) propagate security events to connected apps instantly.

71 Event TypesWebhooksCAEP/SSF RFC 8417
Layer 06 / 06
audit.ts
// CAEP/SSF event propagation
await emitSecurityEvent({
  type: "session-revoked",
  subject: userId,
  reason: "credential_change"
}); // -> all subscribed apps
Commission

Start with sign-in that already has security handled.

Switch to sign-in with six layers of defense built in. Activated instantly with one line of SDK.