#!/bin/bash # ================================================================= # ONBOARDING FLOW DEBUG SCRIPT # ================================================================= # This script replicates the exact onboarding flow to debug the 403 issue # Configuration API_BASE="http://localhost:8000" TEST_EMAIL="onboarding.debug.$(date +%s)@bakery.com" TEST_PASSWORD="OnboardingDebug123!" TEST_NAME="Onboarding Debug User" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' echo -e "${CYAN}🔍 ONBOARDING FLOW DEBUG - EXACT REPLICATION${NC}" echo -e "${CYAN}=============================================${NC}" echo "Test Email: $TEST_EMAIL" echo "API Base: $API_BASE" echo "" # Utility functions log_step() { echo -e "${BLUE}📋 $1${NC}" } log_success() { echo -e "${GREEN}✅ $1${NC}" } log_error() { echo -e "${RED}❌ $1${NC}" } log_debug() { echo -e "${PURPLE}🐛 DEBUG: $1${NC}" } extract_json_field() { local json="$1" local field="$2" echo "$json" | python3 -c " import json, sys try: data = json.load(sys.stdin) user = data.get('user', {}) print(user.get('$field', data.get('$field', ''))) except: print('') " 2>/dev/null } # ================================================================= # STEP 1: REGISTER USER (EXACTLY LIKE ONBOARDING SCRIPT) # ================================================================= log_step "Step 1: User Registration (Onboarding Style)" echo "Email: $TEST_EMAIL" echo "Role: admin (explicitly set)" echo "" log_debug "Registering via API Gateway (same as onboarding script)..." REGISTER_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/register" \ -H "Content-Type: application/json" \ -d "{ \"email\": \"$TEST_EMAIL\", \"password\": \"$TEST_PASSWORD\", \"full_name\": \"$TEST_NAME\", \"role\": \"admin\" }") echo "Registration Response:" echo "$REGISTER_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$REGISTER_RESPONSE" # Extract user ID exactly like onboarding script USER_ID=$(echo "$REGISTER_RESPONSE" | python3 -c " import json, sys try: data = json.load(sys.stdin) user = data.get('user', {}) print(user.get('id', '')) except: print('') ") if [ -n "$USER_ID" ]; then log_success "User ID extracted: $USER_ID" else log_error "Failed to extract user ID" exit 1 fi echo "" # ================================================================= # STEP 2: LOGIN (EXACTLY LIKE ONBOARDING SCRIPT) # ================================================================= log_step "Step 2: User Login (Onboarding Style)" LOGIN_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/login" \ -H "Content-Type: application/json" \ -d "{ \"email\": \"$TEST_EMAIL\", \"password\": \"$TEST_PASSWORD\" }") echo "Login Response:" echo "$LOGIN_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$LOGIN_RESPONSE" ACCESS_TOKEN=$(extract_json_field "$LOGIN_RESPONSE" "access_token") if [ -n "$ACCESS_TOKEN" ]; then log_success "Access token obtained: ${ACCESS_TOKEN:0:50}..." else log_error "Failed to extract access token" exit 1 fi echo "" # ================================================================= # STEP 3: CHECK PROFILE ENDPOINT # ================================================================= log_step "Step 3: Check Profile Endpoint" PROFILE_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET "$API_BASE/api/v1/users/me" \ -H "Authorization: Bearer $ACCESS_TOKEN") HTTP_CODE=$(echo "$PROFILE_RESPONSE" | grep "HTTP_CODE:" | cut -d: -f2) PROFILE_RESPONSE=$(echo "$PROFILE_RESPONSE" | sed '/HTTP_CODE:/d') echo "Profile HTTP Status: $HTTP_CODE" echo "Profile Response:" echo "$PROFILE_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$PROFILE_RESPONSE" PROFILE_ROLE=$(extract_json_field "$PROFILE_RESPONSE" "role") echo "" log_debug "Profile role: $PROFILE_ROLE" if [ "$PROFILE_ROLE" = "admin" ]; then log_success "Profile shows admin role correctly" else log_error "Profile shows role '$PROFILE_ROLE', expected 'admin'" fi echo "" # ================================================================= # STEP 4: TEST ADMIN DELETION PREVIEW (EXACTLY LIKE ONBOARDING) # ================================================================= log_step "Step 4: Admin Deletion Preview (Onboarding Style)" log_debug "Calling deletion preview endpoint..." DELETION_PREVIEW_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X GET "$API_BASE/api/v1/users/delete/$USER_ID/deletion-preview" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json") HTTP_CODE=$(echo "$DELETION_PREVIEW_RESPONSE" | grep "HTTP_CODE:" | cut -d: -f2) DELETION_PREVIEW_RESPONSE=$(echo "$DELETION_PREVIEW_RESPONSE" | sed '/HTTP_CODE:/d') echo "Deletion Preview HTTP Status: $HTTP_CODE" echo "Deletion Preview Response:" echo "$DELETION_PREVIEW_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$DELETION_PREVIEW_RESPONSE" case "$HTTP_CODE" in "200") log_success "Deletion preview successful!" ;; "403") log_error "403 Forbidden - Admin access denied!" echo "This is the same error as in onboarding script" ;; "401") log_error "401 Unauthorized - Token issue" ;; *) log_error "Unexpected HTTP status: $HTTP_CODE" ;; esac echo "" # ================================================================= # STEP 5: TEST ACTUAL DELETION (EXACTLY LIKE ONBOARDING) # ================================================================= log_step "Step 5: Admin User Deletion (Onboarding Style)" if [ "$HTTP_CODE" = "200" ]; then log_debug "Attempting actual deletion..." DELETION_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X DELETE "$API_BASE/api/v1/users/delete/$USER_ID" \ -H "Authorization: Bearer $ACCESS_TOKEN") HTTP_CODE=$(echo "$DELETION_RESPONSE" | grep "HTTP_CODE:" | cut -d: -f2) DELETION_RESPONSE=$(echo "$DELETION_RESPONSE" | sed '/HTTP_CODE:/d') echo "Deletion HTTP Status: $HTTP_CODE" echo "Deletion Response:" echo "$DELETION_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$DELETION_RESPONSE" case "$HTTP_CODE" in "200") log_success "Admin deletion successful!" ;; "403") log_error "403 Forbidden - Admin deletion denied!" ;; *) log_error "Deletion failed with HTTP $HTTP_CODE" ;; esac else log_error "Skipping deletion test due to preview failure" fi echo "" # ================================================================= # STEP 6: DETAILED TOKEN ANALYSIS # ================================================================= log_step "Step 6: Detailed Token Analysis" log_debug "Decoding access token from login..." if [ -n "$ACCESS_TOKEN" ]; then # Decode JWT payload JWT_PAYLOAD=$(echo "$ACCESS_TOKEN" | cut -d. -f2) # Add padding if needed JWT_PAYLOAD="${JWT_PAYLOAD}$(printf '%*s' $((4 - ${#JWT_PAYLOAD} % 4)) | tr ' ' '=')" echo "JWT Payload:" echo "$JWT_PAYLOAD" | base64 -d 2>/dev/null | python3 -m json.tool 2>/dev/null || echo "Failed to decode" JWT_ROLE=$(echo "$JWT_PAYLOAD" | base64 -d 2>/dev/null | python3 -c " import json, sys try: data = json.load(sys.stdin) print(data.get('role', 'NOT_FOUND')) except: print('DECODE_ERROR') " 2>/dev/null) echo "" log_debug "JWT token role: $JWT_ROLE" else log_error "No access token available for analysis" fi echo "" # ================================================================= # STEP 7: CHECK GATEWAY VS DIRECT AUTH # ================================================================= log_step "Step 7: Gateway vs Direct Auth Comparison" log_debug "Testing direct auth service call..." DIRECT_PROFILE=$(curl -s -X GET "http://localhost:8001/me" \ -H "Authorization: Bearer $ACCESS_TOKEN" 2>/dev/null || echo "DIRECT_FAILED") if [ "$DIRECT_PROFILE" != "DIRECT_FAILED" ]; then echo "Direct Auth Service Profile:" echo "$DIRECT_PROFILE" | python3 -m json.tool 2>/dev/null || echo "$DIRECT_PROFILE" DIRECT_ROLE=$(extract_json_field "$DIRECT_PROFILE" "role") log_debug "Direct auth service role: $DIRECT_ROLE" else log_debug "Direct auth service call failed (expected in some setups)" fi echo "" # ================================================================= # STEP 8: CHECK AUTH SERVICE LOGS # ================================================================= log_step "Step 8: Auth Service Logs for This Session" log_debug "Checking auth service logs for this user..." AUTH_LOGS=$(docker logs --tail 50 bakery-auth-service 2>/dev/null | grep -E "($TEST_EMAIL|$USER_ID)" || echo "NO_LOGS_FOUND") if [ "$AUTH_LOGS" != "NO_LOGS_FOUND" ]; then echo "Auth Service Logs (filtered for this user):" echo "$AUTH_LOGS" else log_debug "No specific logs found for this user" fi echo "" # ================================================================= # STEP 9: SUMMARY AND COMPARISON # ================================================================= log_step "Step 9: Onboarding Flow Analysis Summary" echo -e "${CYAN}🔍 ONBOARDING FLOW ANALYSIS${NC}" echo -e "${CYAN}===========================${NC}" echo "" echo "Registration Results:" echo " User ID: $USER_ID" echo " Access Token: $([ -n "$ACCESS_TOKEN" ] && echo 'YES' || echo 'NO')" echo "" echo "Authentication Flow:" echo " Profile Role: $PROFILE_ROLE" echo " JWT Role: $JWT_ROLE" echo " Direct Auth Role: ${DIRECT_ROLE:-'NOT_TESTED'}" echo "" echo "Admin Endpoint Tests:" echo " Deletion Preview: HTTP $HTTP_CODE" echo " Admin Access: $([ "$HTTP_CODE" = "200" ] && echo 'SUCCESS' || echo 'FAILED')" echo "" if [ "$HTTP_CODE" != "200" ]; then echo -e "${RED}🚨 ISSUE IDENTIFIED:${NC}" echo "The onboarding flow is still getting 403 errors" echo "" echo -e "${YELLOW}Possible causes:${NC}" echo "1. Token from login different from registration token" echo "2. Gateway headers not set correctly" echo "3. Role being overridden somewhere in the flow" echo "4. Cache or session issue" echo "" echo -e "${YELLOW}Next steps:${NC}" echo "1. Compare JWT tokens from registration vs login" echo "2. Check gateway request headers" echo "3. Verify auth service restart picked up the fix" echo "4. Check if there are multiple auth service instances" else log_success "Onboarding flow working correctly!" fi echo "" echo -e "${CYAN}Manual commands to investigate:${NC}" echo "# Check user in database:" echo "docker exec bakery-auth-db psql -U auth_user -d auth_db -c \"SELECT id, email, role FROM users WHERE email='$TEST_EMAIL';\"" echo "" echo "# Restart auth service:" echo "docker-compose restart auth-service" echo "" echo "# Check auth service status:" echo "docker-compose ps auth-service"