diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md new file mode 100644 index 0000000..a0dfd60 --- /dev/null +++ b/DEPLOYMENT_GUIDE.md @@ -0,0 +1,465 @@ +# Deployment Guide: Farm Auth Service on AWS Lightsail + +This guide will help you deploy the Farm Auth Service on AWS Lightsail Ubuntu server with the domain `auth.livingai.app`. + +## Prerequisites + +- AWS Lightsail Ubuntu server (at least 1GB RAM recommended) +- Domain name `auth.livingai.app` pointing to your Lightsail server IP +- Access to AWS Console (for database if using AWS RDS) +- SSH access to your Lightsail server + +--- + +## Step 1: Set Up AWS Lightsail Instance + +1. **Create Lightsail Instance** + - Go to AWS Lightsail Console + - Click "Create instance" + - Choose: + - Platform: Linux/Unix + - Blueprint: Ubuntu 22.04 LTS (or latest) + - Instance plan: At least $5/month (1GB RAM) + - Name: `auth-service-server` + - Click "Create instance" + +2. **Configure Static IP** + - In Lightsail, go to Networking โ†’ Static IPs + - Click "Create static IP" + - Attach to your instance + - **Note the static IP address** - you'll need it for DNS configuration + +3. **Configure Firewall (Security Groups)** + - Go to Networking โ†’ Firewall + - Add rules: + - HTTP (port 80) - Allow from Anywhere + - HTTPS (port 443) - Allow from Anywhere + - SSH (port 22) - Allow from Your IP (for security) + - Custom TCP 3000 - Allow from localhost only (for Node.js app) + +--- + +## Step 2: Configure DNS + +1. **Point Domain to Lightsail IP** + - Go to your domain registrar (where you manage livingai.app) + - Add/Update A record: + - Type: A + - Name: auth (or @ if using subdomain) + - Value: Your Lightsail static IP address + - TTL: 300 (5 minutes) + - Wait for DNS propagation (can take up to 48 hours, usually faster) + +2. **Verify DNS** + ```bash + # On your local machine + nslookup auth.livingai.app + # Should return your Lightsail IP + ``` + +--- + +## Step 3: Initial Server Setup (SSH into server) + +1. **Connect to Server** + ```bash + # Download SSH key from Lightsail or use existing key + ssh -i /path/to/your-key.pem ubuntu@your-lightsail-ip + ``` + +2. **Update System** + ```bash + sudo apt update && sudo apt upgrade -y + ``` + +3. **Install Node.js (v18 or higher)** + ```bash + # Install Node.js using NodeSource repository + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo apt install -y nodejs + + # Verify installation + node --version + npm --version + ``` + +4. **Install Nginx** + ```bash + sudo apt install -y nginx + sudo systemctl start nginx + sudo systemctl enable nginx + ``` + +5. **Install PM2 (Process Manager)** + ```bash + sudo npm install -g pm2 + ``` + +6. **Install Git** + ```bash + sudo apt install -y git + ``` + +7. **Install Certbot (for SSL)** + ```bash + sudo apt install -y certbot python3-certbot-nginx + ``` + +--- + +## Step 4: Deploy Application Code + +1. **Clone Repository** + ```bash + # Create application directory + cd /home/ubuntu + mkdir -p apps + cd apps + + # Clone your repository (adjust URL as needed) + git clone farm-auth-service + # OR if you need to upload manually: + # scp -r /path/to/farm-auth-service ubuntu@your-ip:/home/ubuntu/apps/ + ``` + +2. **Navigate to Project Directory** + ```bash + cd farm-auth-service + ``` + +3. **Install Dependencies** + ```bash + npm install --production + ``` + +--- + +## Step 5: Configure Environment Variables + +1. **Create .env File** + ```bash + cp example.env .env + nano .env + ``` + +2. **Configure .env File** (Update these values) + ```env + # Database Mode + DATABASE_MODE=aws + + # AWS Configuration (for SSM Parameter Store) + AWS_REGION=ap-south-1 + AWS_ACCESS_KEY_ID=your_aws_access_key_here + AWS_SECRET_ACCESS_KEY=your_aws_secret_key_here + DB_USE_READONLY=false + + # Database connection (auto-detected from SSM if not set) + # DB_HOST=db.livingai.app + # DB_PORT=5432 + # DB_NAME=livingai_test_db + + # JWT Configuration (IMPORTANT: Generate new secrets for production!) + JWT_ACCESS_SECRET=your_strong_random_secret_here_min_32_chars + JWT_REFRESH_SECRET=your_strong_random_secret_here_min_32_chars + JWT_ACCESS_TTL=15m + JWT_REFRESH_TTL=7d + + # Redis Configuration (Optional - for rate limiting) + # REDIS_URL=redis://your-redis-host:6379 + # Or if password protected: + # REDIS_URL=redis://:password@your-redis-host:6379 + + # Application Configuration + NODE_ENV=production + PORT=3000 + TRUST_PROXY=true + + # CORS Configuration (REQUIRED for production) + CORS_ALLOWED_ORIGINS=https://your-mobile-app-domain.com,https://app.livingai.app + # Add all domains that will access this API + + # Twilio Configuration (if using SMS OTP) + # TWILIO_ACCOUNT_SID=your_twilio_account_sid + # TWILIO_AUTH_TOKEN=your_twilio_auth_token + # TWILIO_PHONE_NUMBER=+1234567890 + + # Admin Dashboard (optional) + # ENABLE_ADMIN_DASHBOARD=false + ``` + +3. **Generate Strong JWT Secrets** (Do this on your local machine) + ```bash + # Generate random secrets (64 characters each) + node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" + node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" + ``` + Copy the output to `JWT_ACCESS_SECRET` and `JWT_REFRESH_SECRET` + +4. **Secure .env File** + ```bash + chmod 600 .env + ``` + +--- + +## Step 6: Configure Nginx Reverse Proxy + +1. **Create Nginx Configuration** + ```bash + sudo nano /etc/nginx/sites-available/auth.livingai.app + ``` + +2. **Add Configuration** (Before SSL) + ```nginx + server { + listen 80; + server_name auth.livingai.app; + + location / { + proxy_pass http://localhost:3000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_cache_bypass $http_upgrade; + } + } + ``` + +3. **Enable Site** + ```bash + sudo ln -s /etc/nginx/sites-available/auth.livingai.app /etc/nginx/sites-enabled/ + sudo nginx -t # Test configuration + sudo systemctl reload nginx + ``` + +--- + +## Step 7: Set Up SSL Certificate (Let's Encrypt) + +1. **Obtain SSL Certificate** + ```bash + sudo certbot --nginx -d auth.livingai.app + ``` + - Follow prompts (enter email, agree to terms) + - Choose redirect HTTP to HTTPS (option 2) + +2. **Verify Auto-renewal** + ```bash + sudo certbot renew --dry-run + ``` + +3. **Update Nginx Config** (Certbot should have done this automatically) + Your config should now include SSL and redirect HTTP to HTTPS. + +--- + +## Step 8: Start Application with PM2 + +1. **Start Application** + ```bash + cd /home/ubuntu/apps/farm-auth-service + pm2 start src/index.js --name "auth-service" + ``` + +2. **Save PM2 Configuration** + ```bash + pm2 save + pm2 startup + # Copy and run the command it outputs (starts PM2 on boot) + ``` + +3. **PM2 Useful Commands** + ```bash + pm2 list # View running processes + pm2 logs auth-service # View logs + pm2 restart auth-service # Restart service + pm2 stop auth-service # Stop service + pm2 monit # Monitor resources + ``` + +--- + +## Step 9: Configure Firewall (UFW) + +1. **Set Up Firewall Rules** + ```bash + sudo ufw allow OpenSSH + sudo ufw allow 'Nginx Full' + sudo ufw enable + sudo ufw status + ``` + +--- + +## Step 10: Test Deployment + +1. **Check Application Status** + ```bash + pm2 status + pm2 logs auth-service --lines 50 + ``` + +2. **Test API Endpoint** + ```bash + # From server + curl http://localhost:3000/health + + # From your local machine (should work via domain) + curl https://auth.livingai.app/health + ``` + +3. **Check Nginx Logs** + ```bash + sudo tail -f /var/log/nginx/access.log + sudo tail -f /var/log/nginx/error.log + ``` + +--- + +## Step 11: Database Setup (if using AWS RDS) + +1. **Ensure Database is Accessible** + - Your Lightsail instance should be able to connect to your AWS RDS instance + - Check security groups allow connection from Lightsail IP + - Verify SSM Parameter Store has correct credentials + +2. **Test Database Connection** + ```bash + cd /home/ubuntu/apps/farm-auth-service + node -e "require('./src/db').then(() => console.log('DB Connected')).catch(e => console.error(e))" + ``` + +--- + +## Step 12: Optional - Set Up Redis (for Rate Limiting) + +If you want to use Redis for rate limiting: + +1. **Option A: Install Redis on Same Server** + ```bash + sudo apt install -y redis-server + sudo systemctl start redis-server + sudo systemctl enable redis-server + ``` + Then update `.env`: + ```env + REDIS_URL=redis://localhost:6379 + ``` + +2. **Option B: Use AWS ElastiCache** + - Create ElastiCache Redis cluster + - Update `.env` with ElastiCache endpoint: + ```env + REDIS_URL=redis://your-elasticache-endpoint:6379 + ``` + +--- + +## Monitoring and Maintenance + +### View Logs +```bash +pm2 logs auth-service +pm2 logs auth-service --err # Error logs only +pm2 logs auth-service --out # Output logs only +``` + +### Restart Service +```bash +pm2 restart auth-service +``` + +### Update Application +```bash +cd /home/ubuntu/apps/farm-auth-service +git pull # or upload new files +npm install --production +pm2 restart auth-service +``` + +### Monitor Resources +```bash +pm2 monit +htop # System resources +``` + +--- + +## Troubleshooting + +### Application Not Starting +1. Check logs: `pm2 logs auth-service` +2. Verify .env file exists and has correct values +3. Check database connectivity +4. Verify all dependencies installed: `npm list` + +### 502 Bad Gateway +- Check if app is running: `pm2 status` +- Check app logs: `pm2 logs auth-service` +- Verify port 3000 is listening: `netstat -tlnp | grep 3000` +- Check Nginx error logs: `sudo tail -f /var/log/nginx/error.log` + +### SSL Certificate Issues +- Verify DNS points to correct IP: `nslookup auth.livingai.app` +- Check certificate: `sudo certbot certificates` +- Renew manually: `sudo certbot renew` + +### Database Connection Issues +- Verify AWS SSM parameters are correct +- Check AWS credentials in .env +- Test database connectivity from server +- Check security group allows connection + +--- + +## Security Checklist + +- [ ] Strong JWT secrets generated and stored securely +- [ ] .env file has 600 permissions +- [ ] Firewall configured (UFW) +- [ ] SSL certificate installed and auto-renewal working +- [ ] CORS configured with specific allowed origins (not *) +- [ ] AWS credentials have minimal required permissions +- [ ] Regular security updates: `sudo apt update && sudo apt upgrade` +- [ ] PM2 logs are monitored +- [ ] Database credentials stored in SSM (not in .env) + +--- + +## Backup Strategy + +1. **Database Backups** + - Set up automated RDS snapshots in AWS Console + - Or use pg_dump for manual backups + +2. **Application Code** + - Code is in Git repository (already backed up) + - Keep .env file backed up securely (encrypted) + +3. **Configuration** + - Document all configuration changes + - Keep .env template versioned (without secrets) + +--- + +## Next Steps + +1. Set up monitoring/alerting (e.g., CloudWatch, PM2 Plus) +2. Configure log rotation for PM2 +3. Set up CI/CD pipeline for automated deployments +4. Configure health checks and auto-restart on failure +5. Set up database backups schedule + +--- + +## Support + +For issues, check: +- Application logs: `pm2 logs auth-service` +- Nginx logs: `/var/log/nginx/` +- System logs: `journalctl -xe` + diff --git a/MIGRATION_SUMMARY.md b/MIGRATION_SUMMARY.md deleted file mode 100644 index af0e415..0000000 --- a/MIGRATION_SUMMARY.md +++ /dev/null @@ -1,159 +0,0 @@ -# AWS Database Migration - Implementation Summary - -## โœ… Completed Changes - -All code changes have been implemented to migrate from local Docker PostgreSQL to AWS PostgreSQL using AWS SSM Parameter Store for secure credential management. - -## ๐Ÿ“ Files Modified - -### 1. `src/utils/awsSsm.js` -**Changes:** -- โœ… Updated to use correct SSM parameter paths: - - Read-Write: `/test/livingai/db/app` - - Read-Only: `/test/livingai/db/app/readonly` -- โœ… Added support for `DB_USE_READONLY` environment variable -- โœ… Improved error handling with detailed error messages -- โœ… Added `buildDatabaseConfig()` function for SSL support -- โœ… Updated credential validation and parsing - -### 2. `src/db.js` -**Changes:** -- โœ… Added SSL configuration for self-signed certificates -- โœ… Updated to use `buildDatabaseConfig()` instead of connection string -- โœ… Improved error handling and logging -- โœ… Auto-detection of AWS database when `DB_HOST=db.livingai.app` -- โœ… Connection pool configuration (max: 20, idleTimeout: 30s) - -### 3. `src/config.js` -**Changes:** -- โœ… Updated to require AWS credentials when using SSM -- โœ… Removed `DATABASE_URL` from required env vars when `USE_AWS_SSM=true` -- โœ… Added validation for AWS credentials - -### 4. Documentation -**New Files:** -- โœ… `docs/getting-started/AWS_DATABASE_MIGRATION.md` - Complete migration guide -- โœ… `docs/getting-started/ENV_VARIABLES_REFERENCE.md` - Environment variables reference -- โœ… `MIGRATION_SUMMARY.md` - This file - -## ๐Ÿ”’ Security Implementation - -### โœ… Credentials Management -- **NO database credentials in `.env` files** -- Credentials fetched from AWS SSM Parameter Store at runtime -- Only AWS credentials (for SSM access) in `.env` -- Supports both read-write and read-only users - -### โœ… SSL Configuration -- SSL enabled with `rejectUnauthorized: false` for self-signed certificates -- Connection string includes `?sslmode=require` -- Proper SSL configuration in connection pool - -## ๐Ÿ“‹ Required Environment Variables - -### For AWS Database (Production) -```env -# AWS Configuration (for SSM access) -AWS_REGION=ap-south-1 -AWS_ACCESS_KEY_ID=your_aws_access_key -AWS_SECRET_ACCESS_KEY=your_aws_secret_key -USE_AWS_SSM=true - -# JWT Configuration -JWT_ACCESS_SECRET=your_secret -JWT_REFRESH_SECRET=your_secret -``` - -### Optional -```env -DB_USE_READONLY=false # false = read_write_user, true = read_only_user -DB_HOST=db.livingai.app -DB_PORT=5432 -DB_NAME=livingai_test_db -``` - -## ๐Ÿ”„ Migration Steps - -1. **Set up AWS SSM Parameters:** - - Create `/test/livingai/db/app` with read-write user credentials (JSON format) - - Create `/test/livingai/db/app/readonly` with read-only user credentials (optional) - -2. **Update `.env` file:** - - Add AWS credentials (AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) - - Set `USE_AWS_SSM=true` - - Remove any database credentials (DB_USER, DB_PASSWORD, DATABASE_URL) - -3. **Verify IAM Permissions:** - - Ensure IAM user/role has `ssm:GetParameter` permission for both SSM parameter paths - -4. **Test Connection:** - - Start application: `npm start` - - Verify logs show successful SSM credential fetch and database connection - -## ๐Ÿงช Testing Checklist - -- [ ] AWS SSM parameters created with correct paths and JSON format -- [ ] IAM user has SSM read permissions -- [ ] `.env` file has AWS credentials (no DB credentials) -- [ ] `USE_AWS_SSM=true` in `.env` -- [ ] Application starts without errors -- [ ] Database connection established successfully -- [ ] SSL connection working (no SSL errors) -- [ ] API endpoints respond correctly -- [ ] Database queries execute successfully -- [ ] All business logic works as before - -## ๐Ÿ” Verification Commands - -### Check AWS SSM Parameter -```bash -aws ssm get-parameter --name "/test/livingai/db/app" --with-decryption --region ap-south-1 -``` - -### Test Database Connection -```bash -npm start -# Look for these log messages: -# โœ… Successfully fetched DB credentials from SSM: /test/livingai/db/app (read-write user) -# โœ… Using database credentials from AWS SSM Parameter Store -# โœ… Database connection established successfully -``` - -## โš ๏ธ Important Notes - -1. **No Breaking Changes**: All business logic remains unchanged. Only database connection configuration was updated. - -2. **Backward Compatibility**: Local development still works with `DATABASE_URL` when `USE_AWS_SSM=false`. - -3. **Security**: Database credentials are never stored in files. They are fetched from AWS SSM at runtime. - -4. **SSL**: Self-signed certificates are supported via `rejectUnauthorized: false` configuration. - -5. **Connection Pooling**: Configured with sensible defaults (max 20 connections, 30s idle timeout). - -## ๐Ÿ“š Documentation - -For detailed information, see: -- `docs/getting-started/AWS_DATABASE_MIGRATION.md` - Complete migration guide -- `docs/getting-started/ENV_VARIABLES_REFERENCE.md` - Environment variables reference - -## ๐Ÿ› Troubleshooting - -Common issues and solutions are documented in `docs/getting-started/AWS_DATABASE_MIGRATION.md` under the "Troubleshooting" section. - -## โœจ Next Steps - -1. Review the changes in the modified files -2. Set up AWS SSM parameters with your database credentials -3. Update your `.env` file with AWS credentials -4. Test the connection -5. Deploy to your AWS environment - ---- - -**Migration Status**: โœ… Complete -**All Requirements Met**: โœ… Yes -**Security Requirements Met**: โœ… Yes -**Backward Compatibility**: โœ… Maintained - - diff --git a/QUICK_DEPLOY.md b/QUICK_DEPLOY.md new file mode 100644 index 0000000..40e7592 --- /dev/null +++ b/QUICK_DEPLOY.md @@ -0,0 +1,131 @@ +# Quick Deployment Reference - auth.livingai.app + +## TL;DR - Quick Steps + +### 1. Lightsail Setup +- Create Ubuntu 22.04 instance +- Attach static IP +- Open ports: 80, 443, 22 + +### 2. DNS Configuration +- Point `auth.livingai.app` A record to Lightsail static IP + +### 3. Server Setup (SSH into server) +```bash +# Run setup script +cd ~ && wget https://your-repo/setup-server.sh +bash setup-server.sh + +# OR manually: +sudo apt update && sudo apt upgrade -y +curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - +sudo apt install -y nodejs nginx git certbot python3-certbot-nginx +sudo npm install -g pm2 +``` + +### 4. Deploy Application +```bash +cd ~/apps +git clone farm-auth-service +cd farm-auth-service +npm install --production +cp example.env .env +nano .env # Configure environment variables +``` + +### 5. Configure Nginx +```bash +sudo nano /etc/nginx/sites-available/auth.livingai.app +# Add configuration (see DEPLOYMENT_GUIDE.md) +sudo ln -s /etc/nginx/sites-available/auth.livingai.app /etc/nginx/sites-enabled/ +sudo nginx -t +sudo systemctl reload nginx +``` + +### 6. SSL Certificate +```bash +sudo certbot --nginx -d auth.livingai.app +``` + +### 7. Start Application +```bash +cd ~/apps/farm-auth-service +pm2 start ecosystem.config.js +pm2 save +pm2 startup # Follow instructions +``` + +### 8. Configure Firewall +```bash +sudo ufw allow OpenSSH +sudo ufw allow 'Nginx Full' +sudo ufw enable +``` + +--- + +## Critical Configuration (.env) + +**Required Settings:** +```env +NODE_ENV=production +PORT=3000 +TRUST_PROXY=true +DATABASE_MODE=aws +AWS_REGION=ap-south-1 +AWS_ACCESS_KEY_ID=your_key +AWS_SECRET_ACCESS_KEY=your_secret +JWT_ACCESS_SECRET=generate_strong_secret_min_32_chars +JWT_REFRESH_SECRET=generate_strong_secret_min_32_chars +CORS_ALLOWED_ORIGINS=https://your-app-domain.com,https://app.livingai.app +``` + +**Generate JWT Secrets:** +```bash +node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +``` + +--- + +## Useful Commands + +```bash +# View logs +pm2 logs auth-service + +# Restart +pm2 restart auth-service + +# Status +pm2 status + +# Nginx logs +sudo tail -f /var/log/nginx/error.log +sudo tail -f /var/log/nginx/access.log + +# Test API +curl https://auth.livingai.app/health +``` + +--- + +## Troubleshooting + +**502 Bad Gateway?** +- Check PM2: `pm2 status` +- Check logs: `pm2 logs auth-service` +- Check Nginx: `sudo nginx -t` + +**Can't connect to database?** +- Verify AWS credentials in .env +- Check SSM Parameter Store access +- Test connection: `node -e "require('./src/db')"` + +**SSL issues?** +- Verify DNS: `nslookup auth.livingai.app` +- Renew cert: `sudo certbot renew` + +--- + +For detailed instructions, see `DEPLOYMENT_GUIDE.md` + diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 0000000..b1d32a0 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,27 @@ +// PM2 Ecosystem Configuration File +// Usage: pm2 start ecosystem.config.js + +module.exports = { + apps: [{ + name: 'auth-service', + script: 'src/index.js', + instances: 1, // For single instance, use 1. For cluster mode, use 'max' or number + exec_mode: 'fork', // 'fork' for single instance, 'cluster' for multiple instances + watch: false, // Set to true for development + max_memory_restart: '500M', // Restart if memory exceeds 500MB + env: { + NODE_ENV: 'production', + PORT: 3000 + }, + error_file: './logs/pm2-error.log', + out_file: './logs/pm2-out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true, + autorestart: true, + max_restarts: 10, + min_uptime: '10s', + listen_timeout: 10000, + kill_timeout: 5000 + }] +}; + diff --git a/kotlin_otp_fix.md b/kotlin_otp_fix.md deleted file mode 100644 index c976ed7..0000000 --- a/kotlin_otp_fix.md +++ /dev/null @@ -1,231 +0,0 @@ -# Kotlin OTP Verification Fix - -## Issue Analysis - -The backend `/auth/verify-otp` endpoint expects: -```json -{ - "phone_number": "+919876543210", // Must be E.164 format with + - "code": "123456", // String, not number - "device_id": "optional-device-id", - "device_info": { - "platform": "android", - "model": "device-model", - "os_version": "Android 13", - "app_version": "1.0.0", - "language_code": "en", - "timezone": "Asia/Kolkata" - } -} -``` - -## Common Issues in Kotlin Implementation - -1. **Phone Number Format**: Must include `+` prefix (E.164 format) -2. **OTP Code Type**: Must be sent as string, not integer -3. **Request Body**: Must match exact field names (`phone_number`, `code`) -4. **Missing Device Info**: Backend accepts but doesn't require device_info - -## Fixed Kotlin Code - -### Option 1: Update AuthManager.login() method - -```kotlin -// In AuthManager.kt or AuthApiClient.kt -suspend fun login(phoneNumber: String, otpCode: String): Result { - return try { - // Ensure phone number has + prefix (E.164 format) - val normalizedPhone = if (phoneNumber.startsWith("+")) { - phoneNumber - } else if (phoneNumber.length == 10) { - "+91$phoneNumber" // Add +91 for 10-digit Indian numbers - } else { - phoneNumber // Keep as is if already formatted - } - - // Ensure OTP is string (not integer) - val otpString = otpCode.toString().trim() - - // Get device info - val deviceId = getDeviceId() // Your method to get device ID - val deviceInfo = getDeviceInfo() // Your method to get device info - - val requestBody = mapOf( - "phone_number" to normalizedPhone, - "code" to otpString, - "device_id" to deviceId, - "device_info" to deviceInfo - ) - - val response = apiClient.post("/auth/verify-otp", requestBody) - - if (response.isSuccessful) { - val loginResponse = response.body() // Parse your LoginResponse - Result.success(loginResponse) - } else { - // Handle error response - val errorBody = response.errorBody()?.string() - Result.failure(Exception("OTP verification failed: $errorBody")) - } - } catch (e: Exception) { - Result.failure(e) - } -} - -// Helper function to get device info -private fun getDeviceInfo(): Map { - return mapOf( - "platform" to "android", - "model" to android.os.Build.MODEL, - "os_version" to android.os.Build.VERSION.RELEASE, - "app_version" to getAppVersion(), // Your method - "language_code" to Locale.getDefault().language, - "timezone" to TimeZone.getDefault().id - ) -} - -private fun getDeviceId(): String { - // Use your existing device ID logic - // Could be Android ID, UUID, etc. - return Settings.Secure.getString( - context.contentResolver, - Settings.Secure.ANDROID_ID - ) ?: UUID.randomUUID().toString() -} -``` - -### Option 2: Quick Fix in OtpScreen.kt - -Update your `OtpScreen.kt` to ensure proper formatting: - -```kotlin -@Composable -fun OtpScreen(navController: NavController, phoneNumber: String, name: String) { - val otp = remember { mutableStateOf("") } - val context = LocalContext.current.applicationContext - val scope = rememberCoroutineScope() - val authManager = remember { AuthManager(context, AuthApiClient(context), TokenManager(context)) } - - val isSignInFlow = name == "existing_user" - - // Normalize phone number to ensure it has + prefix - val normalizedPhone = remember(phoneNumber) { - if (phoneNumber.startsWith("+")) { - phoneNumber - } else if (phoneNumber.length == 10) { - "+91$phoneNumber" - } else { - phoneNumber - } - } - - Box( - modifier = Modifier.fillMaxSize() - ) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 36.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Spacer(modifier = Modifier.height(200.dp)) - - Text("Enter OTP", fontSize = 24.sp, fontWeight = FontWeight.Medium, color = Color(0xFF364153)) - - Spacer(modifier = Modifier.height(32.dp)) - - TextField( - value = otp.value, - onValueChange = { if (it.length <= 6 && it.all { char -> char.isDigit() }) otp.value = it }, - modifier = Modifier - .fillMaxWidth() - .height(60.dp) - .shadow(elevation = 1.dp, shape = RoundedCornerShape(16.dp)), - shape = RoundedCornerShape(16.dp), - colors = TextFieldDefaults.colors( - focusedContainerColor = Color.White.copy(alpha = 0.9f), - unfocusedContainerColor = Color.White.copy(alpha = 0.9f), - disabledContainerColor = Color.White.copy(alpha = 0.9f), - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - ), - textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center, fontSize = 24.sp), - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number) - ) - - Spacer(modifier = Modifier.height(48.dp)) - - Button( - onClick = { - scope.launch { - // Ensure OTP is not empty and is 6 digits - if (otp.value.length != 6) { - Toast.makeText(context, "Please enter a valid 6-digit OTP", Toast.LENGTH_SHORT).show() - return@launch - } - - // Use normalized phone number - authManager.login(normalizedPhone, otp.value.trim()) - .onSuccess { response -> - if (isSignInFlow) { - navController.navigate("success") { popUpTo("login") { inclusive = true } } - } else { - if (response.needsProfile) { - navController.navigate("create_profile/$name") - } else { - navController.navigate("success") { popUpTo("login") { inclusive = true } } - } - } - } - .onFailure { error -> - // More detailed error handling - val errorMessage = error.message ?: "Invalid or expired OTP" - Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show() - Log.e("OtpScreen", "OTP verification failed", error) - } - } - }, - shape = RoundedCornerShape(16.dp), - colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFFE9A00)), - modifier = Modifier - .fillMaxWidth() - .height(56.dp) - .shadow(elevation = 4.dp, shape = RoundedCornerShape(16.dp)) - ) { - Text("Continue", color = Color.White, fontSize = 16.sp, fontWeight = FontWeight.Medium) - } - } - } -} -``` - -## Key Changes to Check in Your AuthManager/AuthApiClient - -1. **Phone Number Normalization**: Ensure `+` prefix is present -2. **OTP as String**: Send OTP as string, not integer -3. **Request Body Format**: Use exact field names from backend -4. **Error Handling**: Check response status and error body - -## Debugging Steps - -1. **Add Logging**: Log the exact request being sent - ```kotlin - Log.d("AuthManager", "Sending verify-otp: phone=$normalizedPhone, code=$otpString") - Log.d("AuthManager", "Request body: $requestBody") - ``` - -2. **Check Response**: Log the response - ```kotlin - Log.d("AuthManager", "Response code: ${response.code()}") - Log.d("AuthManager", "Response body: ${response.body()?.string()}") - ``` - -3. **Compare with HTML**: Use the same phone number and OTP in HTML test page to verify backend is working - -## Most Likely Issues - -1. **Phone number missing `+` prefix** - Backend normalizes but expects E.164 format -2. **OTP sent as number instead of string** - Backend expects string -3. **Wrong field names** - Must be `phone_number` and `code` (with underscores) -4. **Request body not properly serialized** - Check your JSON serialization - diff --git a/setup-server.sh b/setup-server.sh new file mode 100644 index 0000000..5e0945f --- /dev/null +++ b/setup-server.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# Quick Setup Script for AWS Lightsail Ubuntu Server +# Run this script on your Lightsail server after initial SSH connection +# Usage: bash setup-server.sh + +set -e + +echo "๐Ÿš€ Starting Farm Auth Service Server Setup..." + +# Update system +echo "๐Ÿ“ฆ Updating system packages..." +sudo apt update && sudo apt upgrade -y + +# Install Node.js +echo "๐Ÿ“ฆ Installing Node.js..." +if ! command -v node &> /dev/null; then + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo apt install -y nodejs +else + echo "โœ… Node.js already installed: $(node --version)" +fi + +# Install Nginx +echo "๐Ÿ“ฆ Installing Nginx..." +if ! command -v nginx &> /dev/null; then + sudo apt install -y nginx + sudo systemctl start nginx + sudo systemctl enable nginx +else + echo "โœ… Nginx already installed" +fi + +# Install PM2 +echo "๐Ÿ“ฆ Installing PM2..." +if ! command -v pm2 &> /dev/null; then + sudo npm install -g pm2 +else + echo "โœ… PM2 already installed: $(pm2 --version)" +fi + +# Install Git +echo "๐Ÿ“ฆ Installing Git..." +sudo apt install -y git + +# Install Certbot +echo "๐Ÿ“ฆ Installing Certbot..." +sudo apt install -y certbot python3-certbot-nginx + +# Create application directory +echo "๐Ÿ“ Creating application directory..." +mkdir -p ~/apps +cd ~/apps + +# Create logs directory +echo "๐Ÿ“ Creating logs directory..." +mkdir -p ~/apps/farm-auth-service/logs + +echo "โœ… Server setup completed!" +echo "" +echo "Next steps:" +echo "1. Clone your repository: cd ~/apps && git clone farm-auth-service" +echo "2. Install dependencies: cd farm-auth-service && npm install --production" +echo "3. Configure .env file: cp example.env .env && nano .env" +echo "4. Configure Nginx (see DEPLOYMENT_GUIDE.md)" +echo "5. Set up SSL: sudo certbot --nginx -d auth.livingai.app" +echo "6. Start application: pm2 start ecosystem.config.js" +