Security Model
How NETWORKCOIN.ID protects your users and your applications.
OAuth 2.1 Compliance
- PKCE Required — All authorization requests must include a
code_challenge(S256). Prevents authorization code interception. - No Implicit Flow — Only authorization code flow. Tokens never appear in URLs.
- State Parameter — Recommended to prevent CSRF attacks.
Token Security
| Token | Format | Lifetime | Notes |
|---|---|---|---|
| Access Token | RS256 JWT | 1 hour | Verifiable without calling our servers |
| ID Token | RS256 JWT + PQ sig | 1 hour | Contains identity claims filtered by scope |
| Refresh Token | Opaque (SHA-256 hashed) | 30 days | Rotated on every use |
Refresh Token Rotation
Every time a refresh token is used, a new one is issued and the old one is revoked. If a revoked token is ever reused (indicating theft), all tokens for that client+user are immediately revoked.
Post-Quantum Hybrid Signing
ID tokens are dual-signed:
- RS256 — Classical RSA signature. Standard OIDC clients verify this.
- EdDSA (Ed25519) — Post-quantum bridge signature in
pq_sigclaim. PQ-aware clients can verify both.
When Node.js/WebCrypto adds ML-DSA (CRYSTALS-Dilithium) support, the Ed25519 bridge will be swapped to ML-DSA-65 with no protocol changes.
Signing Key Management
- RS256 (RSA 2048-bit) + Ed25519 keypairs
- Published at
/.well-known/jwks.json - Rotatable by superadmins via the security dashboard
- Old keys remain active for 24 hours after rotation (grace period), then auto-deactivate
Rate Limiting
Multi-tier rate limiting per IP AND per account:
| Endpoint | Burst | Sustained | Lockout |
|---|---|---|---|
| Login (per IP) | 5/min | 15/hr | 1 min → 15 min |
| Login (per email) | 5/min | 15/hr | Account locked 15 min |
| Registration | 3/5min | 10/hr | 5 min → 30 min |
| SIWE (per wallet) | 5/5min | 10/hr | Wallet locked 5 min → 1 hr |
| Token Exchange | 60/min | 600/hr | Window |
| Password Reset | 3/5min | 5/hr | 10 min → 1 hr |
| Payment Charge | 10/min | 100/hr | OAuth token required + payments scope |
Wallet Authentication (SIWE)
- Non-custodial — We never store or access private keys
- EIP-4361 (SIWE) — Standard Sign-In with Ethereum messages
- Nonce-based — Challenges expire after 5 minutes, single-use
- Server-side verification — Signatures verified via
viem.verifyMessage()
Session Security
- HS256-signed JWTs in httpOnly, Secure, SameSite=Lax cookies
- 24-hour expiration
- Every session tracked in database with IP, device, user agent
- Users can view and revoke sessions from their dashboard
- Password reset automatically revokes all sessions
Audit Logging
Every security-relevant action is logged with event type, action, user ID, IP address, timestamp, and contextual details:
- Login attempts (success and failure)
- Registration, email verification
- Password changes and resets
- OAuth consent grants and revocations
- Token issuance, refresh, and revocation
- Session creation and revocation
- Signing key rotations
- Superadmin actions (suspend, promote, demote)
- Payment method additions and removals
- Payment charges (success and failure)
Payment Security
- PCI compliant via Stripe — Card numbers never touch our servers. Stripe Elements sends them directly to Stripe.
- We only store references — Stripe customer ID, payment method ID, last 4 digits, and expiry for display.
- Scope-gated — Apps can only charge if the user explicitly granted the
paymentsscope during OAuth consent. - OAuth token required — The charge API validates the access token and checks for the payments scope before processing.
- Minimum 1 card — Users cannot remove their last payment method (same as Apple).