Security model
IdentSphere's security model rests on five principles. If you understand these, the rest of the security choices flow naturally.
1. Zero phone-home
The SDK never opens a network connection to any server controlled by the IdentSphere maintainers — at any tier. No license-check ping. No usage analytics. No install ping. No CVE alerts pushed from us to you. Nothing.
This means:
- Air-gapped deployments work out of the box
- Compliance reviews (HIPAA, SOC2, EU GDPR) cannot find any third-party data flow to flag
- The IdentSphere project could disappear tomorrow and your auth keeps running indefinitely
License verification (for the paid premium modules, when those ship) is offline-only via ed25519-signed JWTs verified against an embedded public key.
2. You own all the data
Every byte of user data lives in your Postgres. IdentSphere never persists data anywhere we can see. We don't have your users' emails, password hashes, MFA secrets, OAuth tokens, audit logs, or session data — by design, with no exception.
This is true at every license tier.
3. Standard primitives only
We use:
| Concern | Algorithm | Why |
|---|---|---|
| Password hashing | Argon2id (preferred) + bcrypt (legacy) | NIST + OWASP recommended; every other auth provider can import these hashes |
| Token signing | RS256 (production) + HS256 (dev) | Asymmetric, JWKS-publishable; every JWT library validates these |
| MFA | TOTP (RFC 6238) | Compatible with every authenticator app |
| Passkeys | W3C WebAuthn level 2 | Industry standard, hardware-backed |
| OAuth | OAuth 2.1 + OIDC | RFC 6749 + 8252 compliant |
| Cookie binding | DPoP (RFC 9449) | Tokens cryptographically bound to client keypair |
| Webhook signing | HMAC-SHA256 with timestamp | Same as Stripe / GitHub patterns |
No proprietary anything. Every artifact IdentSphere issues can be validated by a third-party library in any language. This is the anti-lock-in promise made physical.
4. Fail closed
Authorization decisions default to "no" when the data needed to make the decision is missing.
Examples:
Authorizer::resolve_rolereturnsErr(Forbidden)if noorganization_membershipsrow exists. There's no "default member" fallback that could let a removed user keep their old permissions.validate_jwtchecks theuser_sessionstable; a session with no row is treated as revoked (not as "unknown therefore allow").require_recent_mfadefaults to requiring MFA when the timestamp is ambiguous or unset.- Platform admin lookup defaults to
(false, None)on a database error — a transient outage cannot accidentally grant admin powers.
5. Defense in depth on cookies
Browser sessions are protected by three independent mechanisms:
| Cookie | What it carries | Defense |
|---|---|---|
identsphere_at | Access token (JWT) | HttpOnly — JS can't read it. XSS can't steal it. |
identsphere_rt | Refresh token | HttpOnly + Path=/v1/auth — JS can't read AND only sent to refresh endpoint |
identsphere_csrf | CSRF token | NOT httpOnly — JS reads and echoes in X-IdentSphere-CSRF header on mutating requests |
Production cookies also get Secure + SameSite=Lax.
This means an attacker would need:
- XSS access to your frontend AND the ability to forge a same-origin POST AND knowledge of the user's refresh path — AND the user must trigger that POST before the access token expires (default 15 min).
What IdentSphere does not protect
These are the customer's responsibility — IdentSphere gives you the rope but doesn't tie the knot:
- TLS termination. Run a real TLS reverse proxy (nginx, Caddy, Cloudflare, AWS ALB). IdentSphere has no opinions about how you get there.
- Rate limiting. IdentSphere ships HMAC anti-brute on MFA challenges but
not on the overall request rate. Wire
tower-governor, Cloudflare, or nginx-rate-limit in front. Recommended starting points are in the rate limiting docs. - Secret management.
IDENTSPHERE_JWT_SECRETandIDENTSPHERE_RSA_PRIVATE_KEY_PEMmust come from a real secret manager (AWS Secrets Manager, Vault, Doppler, 1Password CLI). Don't put them in.envfiles in production. - Network segmentation. Run IdentSphere behind a private network if at all possible. Public Postgres is never a good idea.
See also
- Threat model — what we worry about and what attacks the design defeats
- Reverse engineering & licensing — the BSL model explained
- Anti-patterns to avoid — common mistakes hosts make when integrating
- Production checklist — go-live audit