Files
tabungin/AUTH_SETUP.md
dwindown 249f3a9d7d feat: remove OTP gate from transactions, fix categories auth, add implementation plan
- Remove OtpGateGuard from transactions controller (OTP verified at login)
- Fix categories controller to use authenticated user instead of TEMP_USER_ID
- Add comprehensive implementation plan document
- Update .env.example with WEB_APP_URL
- Prepare for admin dashboard development
2025-10-11 14:00:11 +07:00

246 lines
6.1 KiB
Markdown

# Custom Authentication Setup Guide
## Overview
Tabungin now uses a custom authentication system with:
- **Primary Methods**: Email/Password + Google OAuth
- **Multi-Factor Authentication (MFA)**: Google Authenticator (TOTP) + Email OTP
## Environment Variables Setup
### Backend (`/apps/api/.env`)
Create `/apps/api/.env` file with the following variables:
```env
# Database Configuration (use your existing PostgreSQL database)
DATABASE_URL="postgresql://user:password@host:port/tabungin?schema=public"
SHADOW_DATABASE_URL="postgresql://user:password@host:port/tabungin_shadow?schema=public"
# JWT Authentication
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
# Google OAuth (for "Continue with Google")
GOOGLE_CLIENT_ID=your-google-client-id-from-google-cloud-console
GOOGLE_CLIENT_SECRET=your-google-client-secret-from-google-cloud-console
GOOGLE_CALLBACK_URL=http://localhost:3001/api/auth/google/callback
# Email Webhook for OTP (n8n webhook URL)
EMAIL_WEBHOOK_URL=https://your-n8n-instance.com/webhook/send-otp
# App Configuration
PORT=3001
WEB_APP_URL=http://localhost:5174
```
### Frontend (`/apps/web/.env.local`)
Create `/apps/web/.env.local` file:
```env
# API Base URL
VITE_API_URL=http://localhost:3001
# Google OAuth Client ID (same as backend)
VITE_GOOGLE_CLIENT_ID=your-google-client-id-from-google-cloud-console
```
## Google OAuth Setup
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing one
3. Enable **Google+ API**
4. Go to **Credentials****Create Credentials****OAuth 2.0 Client ID**
5. Configure OAuth consent screen
6. Add authorized redirect URIs:
- `http://localhost:3001/api/auth/google/callback` (development)
- `https://your-domain.com/api/auth/google/callback` (production)
7. Copy **Client ID** and **Client Secret** to your `.env` files
## Email Webhook Setup (n8n)
### n8n Workflow for Sending OTP Emails
1. Create a new workflow in n8n
2. Add a **Webhook** node:
- Method: POST
- Path: `/send-otp`
3. Add an **Email** node (or your preferred email service):
- To: `{{ $json.to }}`
- Subject: `{{ $json.subject }}`
- Body: `{{ $json.message }}`
4. Activate the workflow
5. Copy the webhook URL to `EMAIL_WEBHOOK_URL` in your `.env`
### Expected Webhook Payload
```json
{
"to": "user@example.com",
"subject": "Tabungin - Your OTP Code",
"message": "Your OTP code is: 123456. This code will expire in 10 minutes.",
"code": "123456"
}
```
## Database Migration
Run the Prisma migration to add auth fields:
```bash
cd apps/api
npx prisma migrate deploy
npx prisma generate
```
## Authentication Flow
### 1. Email/Password Registration
```
POST /api/auth/register
{
"email": "user@example.com",
"password": "securepassword",
"name": "John Doe" (optional)
}
Response:
{
"user": { "id", "email", "name", "avatarUrl", "emailVerified" },
"token": "jwt-token"
}
```
### 2. Email/Password Login
```
POST /api/auth/login
{
"email": "user@example.com",
"password": "securepassword"
}
Response (no MFA):
{
"user": { ... },
"token": "jwt-token"
}
Response (MFA enabled):
{
"requiresOtp": true,
"availableMethods": { "email": true, "totp": false },
"tempToken": "temporary-token-for-otp-verification"
}
```
### 3. Google OAuth Login
```
Frontend redirects to: GET /api/auth/google
Google redirects back to: GET /api/auth/google/callback
Backend redirects to frontend with token
```
### 4. OTP Verification (if MFA enabled)
```
POST /api/auth/verify-otp
{
"tempToken": "temp-token-from-login",
"otpCode": "123456",
"method": "email" or "totp"
}
Response:
{
"user": { ... },
"token": "full-jwt-token"
}
```
## MFA Setup
### Enable Email OTP
```
1. POST /api/otp/email/send (sends OTP to user's email)
2. POST /api/otp/email/verify { "code": "123456" }
```
### Enable TOTP (Google Authenticator)
```
1. POST /api/otp/totp/setup
Response: { "secret": "...", "qrCode": "otpauth://..." }
2. Scan QR code with Google Authenticator app
3. POST /api/otp/totp/verify { "code": "123456" }
```
### Disable MFA
```
POST /api/otp/email/disable
POST /api/otp/totp/disable
```
## API Endpoints
### Authentication
- `POST /api/auth/register` - Register with email/password
- `POST /api/auth/login` - Login with email/password
- `GET /api/auth/google` - Initiate Google OAuth
- `GET /api/auth/google/callback` - Google OAuth callback
- `POST /api/auth/verify-otp` - Verify OTP for MFA
- `GET /api/auth/me` - Get current user (requires JWT)
### OTP/MFA Management
- `GET /api/otp/status` - Get OTP status
- `POST /api/otp/email/send` - Send email OTP
- `POST /api/otp/email/verify` - Verify and enable email OTP
- `POST /api/otp/email/disable` - Disable email OTP
- `POST /api/otp/totp/setup` - Setup TOTP
- `POST /api/otp/totp/verify` - Verify and enable TOTP
- `POST /api/otp/totp/disable` - Disable TOTP
## Security Notes
1. **JWT_SECRET**: Use a strong, random secret (at least 32 characters)
2. **HTTPS**: Always use HTTPS in production
3. **Password**: Passwords are hashed with bcrypt (10 rounds)
4. **Token Expiry**: JWT tokens expire in 7 days
5. **Temp Tokens**: OTP temp tokens expire in 5 minutes
6. **Email OTP**: Codes expire in 10 minutes
## Development vs Production
### Development
- Use `http://localhost:3001` for API
- Use `http://localhost:5174` for frontend
- Email OTP codes are logged to console if webhook fails
### Production
- Update all URLs to your production domain
- Use environment-specific `.env` files
- Set up proper email service (not just n8n webhook)
- Use HTTPS everywhere
- Rotate JWT_SECRET regularly
## Troubleshooting
### "No token provided" error
- Make sure you're sending the JWT token in the `Authorization: Bearer <token>` header
### Google OAuth not working
- Check that redirect URIs match exactly in Google Cloud Console
- Verify GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are correct
### Email OTP not received
- Check n8n webhook URL is correct and workflow is active
- Check backend console logs for OTP code (development mode)
### TOTP not working
- Make sure time is synced on both server and client
- Verify the secret was saved correctly in database