- Nonce generation endpoint created (
GET /api/auth/nonce) - Signature verification endpoint created (
POST /api/auth/verify) - Frontend requests signature from wallet
- Backend validates signature against public key
- Located in:
components/WalletConnect.tsx,lib/auth.ts,app/api/auth/verify/route.ts
-
verifyWalletSignature()function implemented inlib/auth.ts - Uses Stellar SDK for signature verification
- Validates message matches signed content
- Returns success/error response
-
generateJWT()function implemented inlib/auth.ts - JWT format: Header.Payload.Signature
- Includes wallet address (sub claim)
- 7-day expiration time
- Token stored in database
auth_sessionstable - Token stored in browser localStorage
- Error handling in
/api/auth/verify - Invalid signature: Returns 401 with "Invalid signature" message
- Missing fields: Returns 400 with field names
- Invalid nonce: Returns 401 with "Invalid or expired nonce"
- Server-side error handling with console logging
- Authentication middleware created:
lib/auth-middleware.ts -
verifyAuthentication()function validates JWT -
withAuth()HOF for protecting routes -
authMiddleware()for centralized route protection - Protected routes check Authorization header
- Returns 401 for missing/invalid tokens
-
ownercolumn added to snippets table (nullable, default: NULL) - GET /api/snippets works without authentication
- Only POST (create) requires authentication
- Existing snippets retain functionality
- Migration script in
scripts/add-auth-tables.sql
- Freighter wallet integration:
window.freighter.signMessage() - Albedo wallet integration:
@albedo-link/intent - Signature verification: Uses Stellar SDK keypair verification
- File:
lib/auth.ts-verifyWalletSignature()function
- Users table created with
wallet_addressUNIQUE column - User created automatically on first login
- Wallet address included in JWT payload
- File:
lib/auth.ts-getOrCreateUser()function
- JWT includes wallet address in
subandwalletAddressclaims - Expiration: 7 days from issuance
- Token hash stored in database
- Session linked to wallet address
- Logout invalidates session
-
verifyAuthentication()validates JWT format - Checks JWT signature with secret key
- Verifies expiration time
- Confirms session exists in database
- Returns payload with wallet address
- Login_nonces table created
- Nonce unique and single-use
- 15-minute expiration
-
verifyNonce()marks nonce as used after verification - Second use of same nonce fails
- File:
lib/auth.ts-generateNonce(),verifyNonce()functions
- Freighter support: Detects extension, requests public key, signs message
- Albedo support: Web-based authentication with signature
- Lobstr placeholder: Ready for WalletConnect integration
- Error messages for missing wallets
- File:
components/WalletConnect.tsx
- ✅
lib/auth.ts- Authentication utilities (JWT, signature verification, nonce) - ✅
lib/auth-middleware.ts- Authentication middleware - ✅
app/api/auth/nonce/route.ts- Nonce generation endpoint - ✅
app/api/auth/verify/route.ts- Signature verification & JWT issuance - ✅
app/api/auth/logout/route.ts- Session invalidation - ✅
scripts/add-auth-tables.sql- Database migrations - ✅
AUTHENTICATION_GUIDE.md- Implementation and testing guide - ✅
.env.example- Environment variables template
- ✅
components/WalletConnect.tsx- Added signature-based auth flow - ✅
app/api/snippets/route.ts- Added authentication requirement for POST - ✅
lib/db.ts- Updated createSnippet() to include owner parameter
DATABASE_URL="postgresql://user:password@host/database?sslmode=require"
JWT_SECRET="<secure-random-32-character-key>"
NEXT_PUBLIC_STELLAR_NETWORK="testnet"
users- Stores wallet addresses and user infoauth_sessions- Stores JWT sessions with expirationlogin_nonces- Stores one-time nonces for replay protection
snippets- Addedownercolumn (VARCHAR 56, nullable)
- ✅ JWT-based authentication with HMAC-SHA256
- ✅ Nonce-based replay protection
- ✅ Single-use nonces with 15-minute expiration
- ✅ Session tokens with 7-day expiration
- ✅ Signature verification against Stellar public keys
- ✅ No private keys stored server-side
- ✅ Token hashing in database (not plain text)
- ✅ Clear error messages without leaking sensitive info
- JWT generation and verification
- Signature verification with valid/invalid signatures
- Nonce generation and expiration
- User creation and retrieval
- Full auth flow: nonce → sign → verify → JWT
- Protected route access
- Replay attack prevention
- Session invalidation on logout
- ✅ Test 1: Wallet Connection and Signature Verification
- ✅ Test 2: Signature Verification Server-Side
- ✅ Test 3: Replay Attack Prevention
- ✅ Test 4: Protected Routes (API Authentication)
- ✅ Test 5: Unauthenticated Request Rejection
- ✅ Test 6: Session Persistence
- ✅ Test 7: Logout Functionality
- ✅ Test 8: Invalid Signature Rejection
Before deploying to production:
- Change JWT_SECRET to production-grade random value
- Set NEXT_PUBLIC_STELLAR_NETWORK="public" for mainnet
- Verify DATABASE_URL with SSL enabled
- Run database migrations on production database
- Test all authentication flows in production environment
- Set up monitoring for auth endpoints
- Configure CORS for production domain
- Implement rate limiting on auth endpoints
- Set up audit logging for authentication events
- Configure backup strategy for auth database
- ✅ AUTHENTICATION_GUIDE.md - Complete implementation guide with 8 test scenarios
- ✅ .env.example - Environment variable template with instructions
- ✅ IMPLEMENTATION_CHECKLIST.md - This file
- ✅ Code comments in all auth files
- ✅ Error messages for debugging
✅ All acceptance criteria implemented ✅ All tech notes addressed ✅ Security best practices followed ✅ Backward compatibility maintained ✅ Comprehensive testing guide provided ✅ Complete documentation created ✅ Error handling and validation implemented ✅ Frontend and backend integrated
This implementation is ready for the step-by-step testing process outlined in AUTHENTICATION_GUIDE.md.