feat: token rotation, column encryption, HMAC auth, request coalescing#538
Merged
Conversation
Smartdevs17#509, Smartdevs17#510, Smartdevs17#511, Smartdevs17#512) Implements four security and performance improvements: Issue Smartdevs17#512 — Refresh token rotation (NIST SP 800-63B) - backend/src/auth/token-rotation.ts: opaque 32-byte tokens, SHA-256 hashes in DB, token family tree with replay detection; reusing a rotated token auto-revokes the entire family (theft indicator) - Configurable absolute TTL (30 days) and sliding expiration (7 days) - Redis blacklist for immediate family revocation; falls back to DB - Rate limit: 5 refresh requests/minute per user via Lua atomic counter - Routes: POST /auth/login, /auth/refresh, /auth/revoke, /auth/revoke-all, GET /auth/sessions (session management UI) - Prisma RefreshToken model with family tracking and revocation metadata Issue Smartdevs17#511 — Column-level AES-256-GCM encryption for PII - backend/src/encryption/column-encryptor.ts: AES-256-GCM with random IV per value; tenant DEKs derived via HKDF from COLUMN_ENCRYPTION_MASTER_KEY - Deterministic encryption (HMAC-derived IV) for searchable fields (email exact-match lookups) - Key rotation supported via COLUMN_ENCRYPTION_OLD_MASTER_KEY transition - Prisma $extends middleware in encryption/index.ts: transparently encrypts on write, decrypts on read, rewrites WHERE for searchable fields - Applied to User, Payment, SandboxAccount, AuditLog PII columns - Audit log on every decryption; falls back to dev default in non-prod Issue Smartdevs17#510 — HMAC-SHA256 server-to-server request signing - backend/src/middleware/hmac-auth.ts: verifies X-Signature, X-Timestamp, X-Nonce; rejects requests outside ±5-minute window and replayed nonces - Nonce dedup via Redis sorted set; falls back to in-memory Map - Multi-key rotation: supports multiple active SigningKey rows per tenant - Backward compatible: HMAC headers optional; API keys still work - packages/sdk/src/auth/hmac.ts: HmacSigner class for client-side signing - Routes: GET/POST/DELETE /developers/signing-keys, POST .../rotate - Prisma SigningKey model with expiry and isActive for rotation overlap Issue Smartdevs17#509 — Request coalescing for identical concurrent GET calls - backend/src/middleware/request-coalescer.ts: in-process promise registry collapses concurrent identical GETs into one execution - Key: SHA-256(method + path + query + auth-hash) — per-user isolation - Multi-instance: Redis lock + result cache for cross-node coalescing - Per-endpoint configuration (resultTtlMs, timeoutMs, enable/disable) - Error propagation: all waiters receive the same error on failure - Metrics: coalescing hit rate, average wait time via GET /coalesce/metrics - Default opt-in: /api/v1/catalog, /api/v1/gas, /api/v1/pool/metrics Closes Smartdevs17#509 Closes Smartdevs17#510 Closes Smartdevs17#511 Closes Smartdevs17#512
|
@vjuliaife is attempting to deploy a commit to the smartdevs17's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@vjuliaife Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements four security and performance issues in a single cohesive PR.
Issue #512 — Session Token Rotation (NIST SP 800-63B)
familyIdlinking it to its chainindicating token theft
sliding-window limiter)
POST /api/v1/auth/login|refresh|revoke|revoke-allandGET /api/v1/auth/sessionsforsession management UI
RefreshTokenmodel withfamilyId,tokenHash,absoluteExpiresAt,slidingExpiresAt,revokeReasonauditServiceNew files:
backend/src/auth/token-rotation.ts,backend/src/middleware/token-auth.ts,backend/src/routes/token-refresh.tsIssue #511 — Column-Level AES-256-GCM Encryption for PII
$enc1$<iv>$<cipher>$<tag>COLUMN_ENCRYPTION_MASTER_KEYenv var (envelope encryption)HMAC(key, fieldName+value)— enables exact-match WHERE queries without a plaintext search indexreEncrypt()helper usesCOLUMN_ENCRYPTION_OLD_MASTER_KEYduring transition window; DEKcache eviction via
evictTenantKeyCache()$extendsmiddleware encrypts on write (create/update), decrypts on read (find*), andrewrites WHERE conditions for deterministic fields
User.email,User.walletAddress,Payment.fromAddress,Payment.toAddress,SandboxAccount.email,SandboxAccount.walletAddress,AuditLog.ipAddressauditServicefor GDPR/SOC2 audit trailNew files:
backend/src/encryption/column-encryptor.ts,backend/src/encryption/index.tsModified:
backend/src/lib/prisma.ts— wraps Prisma client withwithEncryptionMiddlewareIssue #510 — HMAC-SHA256 API Request Signing
METHOD\nPATH\nTIMESTAMP\nNONCE\nSHA256(body)X-Signature: kid=<id>;hmac-sha256=<hex>,X-Timestamp: <unix ms>,X-Nonce: <random>SETNXwith 5-minute TTL; falls back to in-memory MapSigningKeyrows per tenant; old key expires after configurable overlapwindow (default 5 min) allowing in-flight requests to complete
invalidateKeyCache()on revocationGET/POST /api/v1/developers/signing-keys,DELETE /:keyId,POST /:keyId/rotateHmacSignerclass inpackages/sdk/src/auth/hmac.tsfor automatic request signingSigningKeymodel withkeyId,secretHash(never stores raw secret),isActive,expiresAtNew files:
backend/src/middleware/hmac-auth.ts,backend/src/routes/signing-keys.ts,packages/sdk/src/auth/hmac.tsModified:
packages/sdk/src/index.ts— exportsHmacSignerIssue #509 — Backend Request Coalescing for Concurrent Identical GETs
awaititinstead of executing a new query
SHA-256(method + path + querystring + auth-hash)— auth-context isolation preventscross-user result sharing
resultTtlMs(cache result after completion),timeoutMs(max wait forcoalesced callers),
enabled/api/v1/catalog,/api/v1/gas,/api/v1/pool/metricsGET /api/v1/coalesce/metricsNew file:
backend/src/middleware/request-coalescer.tsSchema Changes
Two new Prisma models added to
backend/prisma/schema.prisma:RefreshToken— token family tracking, hashed token storage, revocation metadataSigningKey— HMAC key management with rotation supportRun
prisma migrate devto apply.Test Plan
POST /api/v1/auth/loginreturnsaccessToken+refreshTokenPOST /api/v1/auth/refreshwith valid token issues new pair and revokes oldPOST /api/v1/auth/refreshwith already-rotated token returnsTOKEN_FAMILY_COMPROMISEDand revokesfamily
GET /api/v1/auth/sessionslists active token familiesPOST /api/v1/developers/signing-keysreturnskeyId+secret; secret not stored rawPOST /api/v1/developers/signing-keys/:id/rotatecreates new key; old key expires after overlapUser.emailstored encrypted in DB; queries by email still work(deterministic)
/api/v1/catalogexecute only one query;GET /api/v1/coalesce/metricsshows coalesced > 0
Closes #509
Closes #510
Closes #511
Closes #512