This HandCash app template implements enterprise-grade security practices for OAuth authentication and session management.
Cross-Site Request Forgery Protection using OAuth 2.0 state parameter:
- Cryptographically secure tokens: Generated using 32-byte random values
- Time-limited validation: 10-minute expiration on CSRF tokens
- Timing-safe comparison: Prevents timing attacks on token validation
- Automatic cleanup: Expired tokens rejected, cookies cleared on validation
Implementation:
lib/csrf-utils.ts- Token generation and validation- Login flow stores CSRF token in httpOnly cookie
- Callback validates state parameter matches stored token
- All mismatches logged as security violations
Enhanced session security with cross-reference protection:
- Unique session IDs: 32-byte cryptographically secure identifiers
- Session metadata tracking:
- IP address (for session hijacking detection)
- User-Agent (for device fingerprinting)
- Creation timestamp
- Last activity timestamp
- Session validation:
- 30-day inactivity expiration
- IP address consistency checks
- User-Agent consistency checks
- Strict enforcement in production (with migration grace period)
- Automatic session refresh: Activity timestamps updated on each request
Implementation:
lib/session-utils.ts- Session lifecycle management- Sessions stored in httpOnly cookies alongside auth tokens
- Middleware validates session integrity on every protected route
Consistent auth validation across all protected routes:
- Single entry point: All routes use
requireAuth()helper - Automatic token validation: Verifies with HandCash service
- Session hijacking detection: Validates IP and User-Agent consistency
- Session expiration checks: Rejects expired sessions
- Bearer token support: Accepts both cookies and Authorization headers
- Automatic cookie updates: Refreshes session activity timestamps
Implementation:
lib/auth-middleware.ts-requireAuth()function- Applied to all protected API routes
Strict admin authorization enforced at middleware level:
- Handle-based verification: Validates authenticated user's handle against
ADMIN_HANDLEenv var - Real-time validation: Fetches user profile on each admin request
- No frontend-only checks: All admin routes protected server-side
- Audit logging: All admin access attempts logged
Implementation:
lib/admin-middleware.ts-requireAdmin()function- Applied to all
/api/admin/*routes - Configuration validation on startup
Protection against brute force and abuse:
- In-memory rate limiting: Configurable limits per endpoint type
- IP-based tracking: Uses x-forwarded-for header for accurate identification
- Endpoint-specific limits:
- Admin endpoints: 1,000 requests/minute
- Auth endpoints: 100 requests/minute
- Payment endpoints: 500 requests/minute
- Item transfer: 500 requests/minute
- General endpoints: 1,000 requests/minute
- Applied to all routes: Every API endpoint protected
Implementation:
lib/rate-limit.ts- Rate limiting utility- Presets for different endpoint types
- Automatic cleanup of expired entries
Note: For multi-instance deployments, consider Redis-based rate limiting.
Security event tracking for compliance and monitoring:
Events logged:
LOGIN_INITIATED- User starts OAuth flowLOGIN_SUCCESS- Successful authenticationLOGIN_FAILED- Authentication failureLOGOUT- User logoutSESSION_EXPIRED- Session timeoutCSRF_VIOLATION- CSRF attack attemptSESSION_HIJACK_ATTEMPT- Session validation failurePROFILE_ACCESS- Profile API accessPAYMENT_INITIATED- Payment startedPAYMENT_SUCCESS- Payment completedPAYMENT_FAILED- Payment error
Audit data captured:
- Event type and timestamp
- Session ID
- User ID (when available)
- IP address
- User-Agent
- Success/failure status
- Additional context details (sensitive data redacted)
Log storage:
- File-based with daily rotation
- 30-day retention policy
- JSON lines format for easy parsing
- Sensitive data automatically redacted
Implementation:
lib/audit-logger.ts- Logging frameworklib/audit-storage.ts- File-based persistence- Automatic redaction of sensitive fields (handles, amounts, etc.)
Robust input sanitization and validation:
- Schema-based validation: Using Zod for type-safe validation
- Handle/ID resolution: Centralized utilities for parsing various input types
- URL validation: Ensures valid webhook URLs
- Type checking: Validates data types before processing
Implementation:
lib/input-validation.ts- Validation utilities- Applied to critical admin routes
- Clear error messages for invalid inputs
Secure webhook endpoint protection:
- Header-based authentication: Validates
app-idandapp-secretheaders - Rate limiting: 100 requests/minute
- Timestamp validation: Prevents replay attacks (5-minute window)
- IP-based tracking: Logs source IP for all webhook requests
Implementation:
app/api/webhooks/payment/route.ts- Validates against environment variables
- Rejects expired timestamps
Startup validation for essential environment variables:
- Required variables checked:
HANDCASH_APP_ID,HANDCASH_APP_SECRET,ADMIN_HANDLE - Fails fast in production: Prevents misconfigured deployments
- Clear error messages: Identifies missing or invalid configuration
Implementation:
lib/config-validator.ts- Configuration checker- Validates on admin route access (first time only)
All authentication cookies use secure settings:
{
httpOnly: true, // Prevents XSS access
secure: true, // HTTPS only in production
sameSite: "lax", // CSRF protection
maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
}- Never stored in localStorage - Prevents XSS theft
- httpOnly cookies only - Not accessible to JavaScript
- Separate from session metadata - Private key isolated from other session data
- Temporary keys expire - 10-minute window for OAuth flow
- Validated before persistence - HandCash verification required
- Login: Generate CSRF token + ephemeral key pair
- OAuth Redirect: Include state parameter for validation
- Callback: Validate CSRF, verify token, create session with metadata
- Requests: Middleware validates session + refreshes activity
- Logout: Clear all cookies, log event
- Proxy-aware: Properly extracts IP from
x-forwarded-forheader - Fallback handling: Gracefully handles missing headers
- First IP in chain: Uses first IP from forwarded header (client's origin IP)
# HandCash OAuth Credentials (Required)
HANDCASH_APP_ID=your_app_id_here
HANDCASH_APP_SECRET=your_app_secret_here
# Admin Configuration (Required for admin features)
ADMIN_HANDLE=your_handcash_handle
# Business Wallet (Required for admin item operations)
BUSINESS_AUTH_TOKEN=your_business_wallet_auth_token
# Webhook Configuration (Optional but recommended)
WEBSITE_URL=https://your-domain.comGet credentials from: HandCash Developer Dashboard
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client Application β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β AuthProvider (React Context) β β
β β - Centralized auth state β β
β β - Auto profile refresh β β
β β - useAuth() hook β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API Routes (Server) β
β β
β /api/auth/login β
β ββ Generate CSRF token β
β ββ Generate key pair β
β ββ Store in httpOnly cookies β
β ββ Rate limit: 100/min β
β ββ Return HandCash OAuth URL β
β β
β /api/auth/callback β
β ββ Rate limit: 200/min β
β ββ Validate CSRF token β
β ββ Verify auth token with HandCash β
β ββ Create session with metadata β
β ββ Store session + private key β
β ββ Log audit event β
β β
β Protected User Routes β
β ββ requireAuth() middleware β
β ββ Rate limiting β
β ββ Validate session consistency β
β ββ Check expiration β
β ββ Update activity timestamp β
β ββ Log access events β
β β
β Admin Routes (/api/admin/*) β
β ββ requireAdmin() middleware β
β ββ Rate limiting (1000/min) β
β ββ Verify handle matches ADMIN_HANDLE β
β ββ Input validation β
β ββ Audit logging β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Security Utilities β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β CSRF Utils β βSession Utils β β Audit Logger β β
β β β β β β β β
β β - Generate β β - Create β β - Log events β β
β β - Validate β β - Validate β β - Redact β β
β β - Timing- β β - Expire β β - Persist β β
β β safe β β - Hijack β β - Rotate β β
β β compare β β detection β β β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β βRate Limiting β βInput Valid. β βConfig Valid. β β
β β β β β β β β
β β - In-memory β β - Zod schemasβ β - Env check β β
β β - IP-based β β - Type safe β β - Format β β
β β - Presets β β - Sanitize β β validate β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- CSRF_VIOLATION: Potential CSRF attack
- SESSION_HIJACK_ATTEMPT: IP/User-Agent mismatch
- Repeated LOGIN_FAILED: Brute force attempts
- Unusual access patterns: Multiple IPs for same session
- Rate limit exceeded: Potential DoS attempt
- Current log:
data/audit.log - Rotated logs:
data/audit-YYYY-MM-DD.log - Retention: 30 days
- Format: JSON Lines (one event per line)
- Enable audit log forwarding to security monitoring service (Sentry, DataDog, etc.)
- Set up alerts for security violations
- Monitor rate limit hits to detect abuse patterns
- Review session hijack attempts regularly
- Consider IP allowlisting for sensitive operations (optional)
- Enable 2FA for admin HandCash accounts (if applicable)
- Regular security audits of auth flows
- Comprehensive authentication: CSRF protection, session management, admin controls
- Rate limiting: All endpoints protected against abuse
- Audit logging: Complete security event tracking with persistence
- Input validation: Schema-based validation on critical routes
- Secure storage: Private keys properly isolated, httpOnly cookies
- Session hijacking detection: IP/User-Agent validation
- Configuration validation: Fails fast on misconfiguration
- In-memory rate limiting: For multi-instance deployments, consider Redis
- Webhook authentication: Currently header-based; consider HMAC signatures if HandCash supports them
- Session validation: Migration grace period for existing sessions with null IP/UA
- RFC 9700: OAuth 2.0 Security Best Practices β
- OWASP Top 10: Most vulnerabilities addressed β
- SOC 2 Ready: Audit logging meets requirements β
- GDPR Compatible: Sensitive data redacted from logs β
- Login creates CSRF token in cookies
- Callback rejects without valid state parameter
- Session tracks IP address and User-Agent
- Protected routes require authentication
- Admin routes require matching handle
- Session expires after 30 days of inactivity
- Logout clears all cookies
- Audit logs capture all auth events
- Rate limiting blocks excessive requests
- Multiple devices can maintain separate sessions
- Invalid tokens are rejected
- Session hijacking detected (IP/UA mismatch)
// 1. Test CSRF protection
// - Clear state cookie before callback
// - Expect: Redirect to /?error=csrf_failed
// 2. Test session hijacking detection
// - Login, copy session cookie
// - Use from different IP/User-Agent
// - Expect: Session validation failure
// 3. Test session expiration
// - Mock Date.now() to +31 days
// - Access protected route
// - Expect: 401 Unauthorized
// 4. Test rate limiting
// - Send 100+ requests in 1 minute
// - Expect: 429 Too Many Requests
// 5. Test admin access
// - Login as non-admin user
// - Attempt admin endpoint
// - Expect: 403 Forbidden
// 6. Test input validation
// - Send malformed JSON to admin endpoints
// - Expect: 400 Bad Request with clear error- RFC 9700: OAuth 2.0 Security Best Practices
- OWASP Session Management Cheat Sheet
- OWASP API Security Top 10
- HandCash SDK Documentation
Found a security issue? Please report it responsibly:
- Do NOT open a public GitHub issue
- Contact the maintainers directly
- Allow reasonable time for patching before disclosure
Last Updated: January 2025
Security Standards: RFC 9700, OWASP Top 10
Compliance: SOC 2 Ready, GDPR Compatible
Status: β
Production Ready