From 0b1e67a76c3f69bf639fbc825773df67f181d05a Mon Sep 17 00:00:00 2001 From: Urtzi Alfaro Date: Sun, 20 Jul 2025 08:49:26 +0200 Subject: [PATCH] Improve auth process 3 --- scripts/test_unified_auth.sh | 413 +++++++++++++++++++-- services/auth/app/services/auth_service.py | 20 +- 2 files changed, 385 insertions(+), 48 deletions(-) diff --git a/scripts/test_unified_auth.sh b/scripts/test_unified_auth.sh index c439dd81..fd92e981 100755 --- a/scripts/test_unified_auth.sh +++ b/scripts/test_unified_auth.sh @@ -1,39 +1,390 @@ #!/bin/bash -echo "Testing Unified Authentication System" +# ================================================================ +# Complete Authentication Test with Registration +# Tests the full user lifecycle: registration โ†’ login โ†’ API access +# ================================================================ -# 1. Get auth token -echo "1. Getting authentication token..." -TOKEN=$(curl -s -X POST http://localhost:8000/api/v1/auth/login \ - -H "Content-Type: application/json" \ - -d '{"email": "test@bakery.com", "password": "testpass123"}' \ - | jq -r '.access_token') +echo "๐Ÿ” Testing Complete Authentication System with Registration" +echo "==========================================================" -echo "Token obtained: ${TOKEN:0:20}..." +# Configuration +API_BASE="http://localhost:8000" +AUTH_BASE="$API_BASE/api/v1/auth" +TEST_EMAIL="test-$(date +%s)@bakery.com" # Unique email for each test +TEST_PASSWORD="SecurePass123!" +TEST_NAME="Test Baker" +TENANT_ID="test-tenant-$(date +%s)" -# 2. Test data service through gateway -echo -e "\n2. Testing data service through gateway..." -curl -s -X GET http://localhost:8000/api/v1/data/sales \ - -H "Authorization: Bearer $TOKEN" \ - -H "X-Tenant-ID: test-tenant" \ - | jq '.' +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color -# 3. Test training service through gateway -echo -e "\n3. Testing training service through gateway..." -curl -s -X POST http://localhost:8000/api/v1/training/jobs \ - -H "Authorization: Bearer $TOKEN" \ - -H "X-Tenant-ID: test-tenant" \ - -H "Content-Type: application/json" \ - -d '{ - "include_weather": true, - "include_traffic": false, - "min_data_points": 30 - }' \ - | jq '.' +# Helper function for colored output +log_step() { + echo -e "${BLUE}๐Ÿ“ $1${NC}" +} -# 4. Test direct service call (should work with headers) -echo -e "\n4. Testing direct service call..." -curl -s -X GET http://localhost:8002/health \ - | jq '.' +log_success() { + echo -e "${GREEN}โœ… $1${NC}" +} -echo -e "\nUnified authentication test complete!" \ No newline at end of file +log_error() { + echo -e "${RED}โŒ $1${NC}" +} + +log_warning() { + echo -e "${YELLOW}โš ๏ธ $1${NC}" +} + +# Helper function to check if service is healthy +check_service_health() { + local service_url=$1 + local service_name=$2 + + log_step "Checking $service_name health..." + + response=$(curl -s -o /dev/null -w "%{http_code}" "$service_url/health") + if [ "$response" = "200" ]; then + log_success "$service_name is healthy" + return 0 + else + log_error "$service_name is not healthy (HTTP $response)" + return 1 + fi +} + +# Check all services are running +log_step "Pre-flight checks..." +echo "" + +# Check API Gateway +if ! check_service_health "$API_BASE" "API Gateway"; then + log_error "API Gateway is not running. Start with: docker-compose up -d" + exit 1 +fi + +# Check Auth Service directly +if ! check_service_health "http://localhost:8001" "Auth Service"; then + log_error "Auth Service is not running. Check: docker-compose logs auth-service" + exit 1 +fi + +# Check Data Service +if ! check_service_health "http://localhost:8004" "Data Service"; then + log_warning "Data Service is not running, but continuing with auth tests..." +fi + +# Check Training Service +if ! check_service_health "http://localhost:8002" "Training Service"; then + log_warning "Training Service is not running, but continuing with auth tests..." +fi + +echo "" +log_step "All systems ready! Starting authentication tests..." +echo "" + +# ================================================================ +# STEP 1: USER REGISTRATION +# ================================================================ + +log_step "Step 1: Registering new user" +echo "Email: $TEST_EMAIL" +echo "Password: $TEST_PASSWORD" +echo "" + +REGISTRATION_RESPONSE=$(curl -s -X POST "$AUTH_BASE/register" \ + -H "Content-Type: application/json" \ + -d "{ + \"email\": \"$TEST_EMAIL\", + \"password\": \"$TEST_PASSWORD\", + \"full_name\": \"$TEST_NAME\" + }") + +echo "Registration Response:" +echo "$REGISTRATION_RESPONSE" | jq '.' + +# Check if registration was successful +if echo "$REGISTRATION_RESPONSE" | jq -e '.id' > /dev/null; then + USER_ID=$(echo "$REGISTRATION_RESPONSE" | jq -r '.id') + log_success "User registration successful! User ID: $USER_ID" +else + log_error "User registration failed!" + echo "Response: $REGISTRATION_RESPONSE" + exit 1 +fi + +echo "" + +# ================================================================ +# STEP 2: USER LOGIN +# ================================================================ + +log_step "Step 2: Logging in with new user credentials" + +LOGIN_RESPONSE=$(curl -s -X POST "$AUTH_BASE/login" \ + -H "Content-Type: application/json" \ + -d "{ + \"email\": \"$TEST_EMAIL\", + \"password\": \"$TEST_PASSWORD\" + }") + +echo "Login Response:" +echo "$LOGIN_RESPONSE" | jq '.' + +# Extract access token +if echo "$LOGIN_RESPONSE" | jq -e '.access_token' > /dev/null; then + ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | jq -r '.access_token') + REFRESH_TOKEN=$(echo "$LOGIN_RESPONSE" | jq -r '.refresh_token') + log_success "Login successful! Token obtained: ${ACCESS_TOKEN:0:20}..." +else + log_error "Login failed!" + echo "Response: $LOGIN_RESPONSE" + exit 1 +fi + +echo "" + +# ================================================================ +# STEP 3: TOKEN VERIFICATION +# ================================================================ + +log_step "Step 3: Verifying access token" + +VERIFY_RESPONSE=$(curl -s -X POST "$AUTH_BASE/verify" \ + -H "Content-Type: application/json" \ + -d "{ + \"token\": \"$ACCESS_TOKEN\" + }") + +echo "Token Verification Response:" +echo "$VERIFY_RESPONSE" | jq '.' + +if echo "$VERIFY_RESPONSE" | jq -e '.valid' > /dev/null; then + log_success "Token verification successful!" +else + log_error "Token verification failed!" + exit 1 +fi + +echo "" + +# ================================================================ +# STEP 4: ACCESSING PROTECTED ENDPOINTS +# ================================================================ + +log_step "Step 4: Testing protected endpoints with authentication" + +# 4a. Get current user info +log_step "4a. Getting current user profile" + +USER_PROFILE_RESPONSE=$(curl -s -X GET "$API_BASE/api/v1/users/me" \ + -H "Authorization: Bearer $ACCESS_TOKEN") + +echo "User Profile Response:" +echo "$USER_PROFILE_RESPONSE" | jq '.' + +if echo "$USER_PROFILE_RESPONSE" | jq -e '.email' > /dev/null; then + log_success "User profile retrieved successfully!" +else + log_warning "User profile endpoint may not be implemented yet" +fi + +echo "" + +# 4b. Test data service through gateway +log_step "4b. Testing data service through gateway" + +DATA_RESPONSE=$(curl -s -X GET "$API_BASE/api/v1/data/sales" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -H "X-Tenant-ID: $TENANT_ID") + +echo "Data Service Response:" +echo "$DATA_RESPONSE" | jq '.' + +if [ "$(echo "$DATA_RESPONSE" | jq -r '.status // "unknown"')" != "error" ]; then + log_success "Data service access successful!" +else + log_warning "Data service returned error (may be expected for new tenant)" +fi + +echo "" + +# 4c. Test training service through gateway +log_step "4c. Testing training service through gateway" + +TRAINING_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/training/jobs" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -H "X-Tenant-ID: $TENANT_ID" \ + -H "Content-Type: application/json" \ + -d '{ + "include_weather": true, + "include_traffic": false, + "min_data_points": 30 + }') + +echo "Training Service Response:" +echo "$TRAINING_RESPONSE" | jq '.' + +if echo "$TRAINING_RESPONSE" | jq -e '.job_id // .message' > /dev/null; then + log_success "Training service access successful!" +else + log_warning "Training service access may have issues" +fi + +echo "" + +# ================================================================ +# STEP 5: TENANT REGISTRATION (OPTIONAL) +# ================================================================ + +log_step "Step 5: Registering a bakery/tenant" + +BAKERY_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/tenants/bakeries" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{ + \"name\": \"Test Bakery $(date +%H%M)\", + \"business_type\": \"bakery\", + \"address\": \"Calle Test 123\", + \"city\": \"Madrid\", + \"postal_code\": \"28001\", + \"phone\": \"+34600123456\" + }") + +echo "Bakery Registration Response:" +echo "$BAKERY_RESPONSE" | jq '.' + +if echo "$BAKERY_RESPONSE" | jq -e '.id' > /dev/null; then + TENANT_ID=$(echo "$BAKERY_RESPONSE" | jq -r '.id') + log_success "Bakery registration successful! Tenant ID: $TENANT_ID" +else + log_warning "Bakery registration endpoint may not be fully implemented" +fi + +echo "" + +# ================================================================ +# STEP 6: TOKEN REFRESH +# ================================================================ + +log_step "Step 6: Testing token refresh" + +REFRESH_RESPONSE=$(curl -s -X POST "$AUTH_BASE/refresh" \ + -H "Content-Type: application/json" \ + -d "{ + \"refresh_token\": \"$REFRESH_TOKEN\" + }") + +echo "Token Refresh Response:" +echo "$REFRESH_RESPONSE" | jq '.' + +if echo "$REFRESH_RESPONSE" | jq -e '.access_token' > /dev/null; then + NEW_ACCESS_TOKEN=$(echo "$REFRESH_RESPONSE" | jq -r '.access_token') + log_success "Token refresh successful! New token: ${NEW_ACCESS_TOKEN:0:20}..." +else + log_warning "Token refresh may not be fully implemented" +fi + +echo "" + +# ================================================================ +# STEP 7: DIRECT SERVICE HEALTH CHECKS +# ================================================================ + +log_step "Step 7: Testing direct service access (without gateway)" + +# Test auth service directly +log_step "7a. Auth service direct health check" +AUTH_HEALTH=$(curl -s -X GET "http://localhost:8001/health") +echo "Auth Service Health:" +echo "$AUTH_HEALTH" | jq '.' + +# Test other services if available +log_step "7b. Other services health check" + +services=("8002:Training" "8003:Forecasting" "8004:Data" "8005:Tenant" "8006:Notification") + +for service in "${services[@]}"; do + port=$(echo $service | cut -d: -f1) + name=$(echo $service | cut -d: -f2) + + health_response=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port/health" 2>/dev/null) + if [ "$health_response" = "200" ]; then + log_success "$name Service (port $port) is healthy" + else + log_warning "$name Service (port $port) is not responding" + fi +done + +echo "" + +# ================================================================ +# STEP 8: LOGOUT +# ================================================================ + +log_step "Step 8: Logging out user" + +LOGOUT_RESPONSE=$(curl -s -X POST "$AUTH_BASE/logout" \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -H "Content-Type: application/json") + +echo "Logout Response:" +echo "$LOGOUT_RESPONSE" | jq '.' + +if echo "$LOGOUT_RESPONSE" | jq -e '.message' > /dev/null; then + log_success "Logout successful!" +else + log_warning "Logout endpoint may not be fully implemented" +fi + +echo "" + +# ================================================================ +# SUMMARY +# ================================================================ + +echo "๐ŸŽ‰ Authentication Test Summary" +echo "===============================" +echo "" +echo "Test User Created:" +echo " ๐Ÿ“ง Email: $TEST_EMAIL" +echo " ๐Ÿ‘ค Name: $TEST_NAME" +echo " ๐Ÿ†” User ID: $USER_ID" +echo "" +echo "Authentication Flow:" +echo " โœ… User Registration" +echo " โœ… User Login" +echo " โœ… Token Verification" +echo " โœ… Protected Endpoint Access" +echo " โœ… Token Refresh" +echo " โœ… User Logout" +echo "" +echo "Services Tested:" +echo " ๐ŸŒ API Gateway" +echo " ๐Ÿ” Auth Service" +echo " ๐Ÿ“Š Data Service (through gateway)" +echo " ๐Ÿค– Training Service (through gateway)" +echo " ๐Ÿข Tenant Service (bakery registration)" +echo "" + +if [ -n "$TENANT_ID" ]; then + echo "Tenant Created:" + echo " ๐Ÿช Tenant ID: $TENANT_ID" + echo "" +fi + +log_success "Complete authentication test finished successfully!" +echo "" +echo "๐Ÿ”ง Development Tips:" +echo " โ€ข Use the created test user for further development" +echo " โ€ข Check service logs with: docker-compose logs [service-name]" +echo " โ€ข View API docs at: http://localhost:8000/docs" +echo " โ€ข Monitor services at: http://localhost:3002" +echo "" +echo "๐Ÿงน Cleanup:" +echo " โ€ข Test user will remain in database for development" +echo " โ€ข To reset: Delete user from auth database or run cleanup script" \ No newline at end of file diff --git a/services/auth/app/services/auth_service.py b/services/auth/app/services/auth_service.py index d68e8cc1..fe44bcdd 100644 --- a/services/auth/app/services/auth_service.py +++ b/services/auth/app/services/auth_service.py @@ -71,7 +71,7 @@ class AuthService: ) # Create new user - hashed_password = SecurityManager.get_password_hash(password) + hashed_password = SecurityManager.hash_password(password) user = User( email=email, hashed_password=hashed_password, @@ -113,14 +113,7 @@ class AuthService: tenant_memberships = await AuthService._get_user_tenants(str(user.id)) # Create tokens - access_token = SecurityManager.create_access_token( - data={ - "user_id": str(user.id), - "email": user.email, - "full_name": user.full_name, - "tenants": tenant_memberships # Include tenant info in token - } - ) + access_token = SecurityManager.create_access_token(user) refresh_token_value = SecurityManager.create_refresh_token(data={"user_id": str(user.id)}) @@ -205,14 +198,7 @@ class AuthService: tenant_memberships = await AuthService._get_user_tenants(str(user.id)) # Create new access token - access_token = SecurityManager.create_access_token( - data={ - "user_id": str(user.id), - "email": user.email, - "full_name": user.full_name, - "tenants": tenant_memberships - } - ) + access_token = SecurityManager.create_access_token(user) return { "access_token": access_token,