LiquiFi — Auth System
SIWE + JWT authentication and authorization system for the Attestify Farcaster mini app.
🏗 Architecture ┌─────────────────────────────────────────────────────────────────────┐ │ FARCASTER MINI APP │ │ │ │ useAuth() hook │ │ │ │ │ ├── signIn() ──────────────────────────────────────────────┐ │ │ ├── signOut() ─────────────────────────────────────────┐ │ │ │ └── authFetch() ──────── all protected API calls │ │ │ └──────────────────────────────────────────────────────────────│────│─┘ │ │ NEXT.JS API ROUTES │ │ │ │ GET /api/auth/nonce ← generate one-time nonce │ │ POST /api/auth/verify ← verify SIWE sig → issue JWT ◄─────│────┘ POST /api/auth/refresh ← rotate access token │ POST /api/auth/logout ← revoke session ◄──────────────────┘
STORAGE LAYER
PostgreSQL (via Prisma) Redis ├── User ├── nonce:{address} TTL 5min └── Session └── blocklist:{token} TTL 8d 🔐 Auth Flow — Step by Step 1️⃣ User clicks "Connect" 2️⃣ Frontend requests wallet address
From window.ethereum (or Farcaster SDK)
3️⃣ Request nonce GET /api/auth/nonce?address=0x...
Backend:
Generates nonce
Stores in Redis (5 min TTL)
Returns pre-built SIWE message
4️⃣ Wallet signs message wallet.signMessage(siweMessage)
No gas
No transaction
Pure signature
5️⃣ Verify signature POST /api/auth/verify { message, signature, fid? }
Backend:
Parse + verify signature (SIWE library)
Validate chain ID (Celo)
Consume nonce (prevents replay)
Optional: Cross-check FID via Neynar
Upsert user in PostgreSQL
Create Session row
Issue:
Access Token (1hr)
Refresh Token (7d)
6️⃣ Store tokens
Frontend stores in localStorage.
Subsequent API calls:
Authorization: Bearer 7️⃣ Refresh flow POST /api/auth/refresh
Verify refresh JWT
Ensure session not revoked
Rotate refresh token
Blocklist old token in Redis
Issue new token pair
📁 Project Structure attestify-auth/ ├── prisma/ │ └── schema.prisma ├── src/ │ ├── app/api/ │ │ ├── auth/ │ │ │ ├── nonce/route.ts │ │ │ ├── verify/route.ts │ │ │ ├── refresh/route.ts │ │ │ └── logout/route.ts │ │ └── user/ │ │ └── profile/route.ts │ ├── lib/ │ │ ├── prisma.ts │ │ ├── redis.ts │ │ ├── jwt.ts │ │ └── useAuth.ts │ ├── middleware/ │ │ └── withAuth.ts │ └── types/ │ └── auth.ts ├── .env.example ├── next.config.mjs ├── tsconfig.json └── package.json ⚙️ Setup 1️⃣ Install dependencies npm install 2️⃣ Configure environment cp .env.example .env.local
Fill in:
DATABASE_URL
REDIS_URL
JWT_ACCESS_SECRET
JWT_REFRESH_SECRET
NEXT_PUBLIC_APP_URL
NEYNAR_API_KEY (optional)
Generate secrets:
openssl rand -base64 64 3️⃣ Set up database npm run db:generate npm run db:push 4️⃣ Run development server npm run dev