# CORS 403 Hatası Çözümü ## ❌ Problem ``` OPTIONS https://goauth.beyhano.net.tr/v1/auth/login Status: 403 Forbidden Origin: https://nextgo.beyhano.net.tr ``` ### Hata Detayları: - **Frontend Origin:** `https://nextgo.beyhano.net.tr` - **Backend:** `https://goauth.beyhano.net.tr` - **HTTP Method:** OPTIONS (preflight request) - **Status:** 403 Forbidden - **Sorun:** CORS middleware sadece `localhost:3000`'e izin veriyor --- ## ✅ Çözüm ### 1. Dynamic CORS Middleware Aktif Edildi **Önce (main.go):** ```go // Hardcoded CORS - sadece localhost r.Use(cors.New(cors.Config{ AllowOrigins: []string{"http://localhost:3000"}, ... })) ``` **Sonra (main.go):** ```go // Dynamic CORS - Database'den okuyor settingsService := services.NewSettingsService() r.Use(middlewares.DynamicCorsMiddleware(settingsService)) ``` ### 2. Whitelist'e Origin Ekleme Production origin'ini whitelist'e ekleyin: ```bash # Admin login TOKEN=$(curl -s -X POST https://goauth.beyhano.net.tr/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token') # Frontend origin'ini whitelist'e ekle curl -X POST https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "origin": "https://nextgo.beyhano.net.tr", "description": "Production Next.js frontend" }' ``` **Başarılı Yanıt:** ```json { "id": "uuid", "origin": "https://nextgo.beyhano.net.tr", "description": "Production Next.js frontend", "is_active": true, "created_by": "admin@gauth.local", "created_at": "2026-02-05T...", "updated_at": "2026-02-05T..." } ``` --- ## 🔧 Dynamic CORS Middleware Nasıl Çalışır? ### Akış: 1. **Request gelir** → `Origin` header kontrol edilir 2. **Database kontrolü** → Whitelist/Blacklist'ten origin aranır 3. **Cache kontrolü** → Redis'te var mı? (1 saat TTL) 4. **Karar:** - ✅ Whitelist'te var → İzin ver - ❌ Blacklist'te var → Reddet (403) - ❌ Hiçbirinde yok → Reddet (403) ### Code (`dynamic_cors_middleware.go`): ```go func DynamicCorsMiddleware(settingsService *services.SettingsService) gin.HandlerFunc { return func(c *gin.Context) { origin := c.Request.Header.Get("Origin") // Check if origin is allowed allowed, err := settingsService.IsOriginAllowed(origin) if !allowed { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "Origin not allowed by CORS policy", }) return } // Set CORS headers c.Writer.Header().Set("Access-Control-Allow-Origin", origin) c.Writer.Header().Set("Access-Control-Allow-Credentials", "true") c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Authorization") c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") c.Writer.Header().Set("Access-Control-Max-Age", "86400") // 24 hours // Handle preflight requests if c.Request.Method == "OPTIONS" { c.AbortWithStatus(http.StatusNoContent) return } c.Next() } } ``` --- ## 🚀 Production Deploy Sonrası Yapılacaklar ### 1. Container'a Bağlan Dokploy dashboard veya SSH ile: ```bash docker exec -it app_auth_central sh ``` ### 2. Admin Kullanıcı Oluştur ```bash ./main seed-admin ``` **Credentials:** - Email: `admin@gauth.local` - Password: `Admin@123` ### 3. Admin Login (Local veya cURL) ```bash TOKEN=$(curl -s -X POST https://goauth.beyhano.net.tr/v1/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@gauth.local","password":"Admin@123"}' | jq -r '.access_token') echo "Token: ${TOKEN:0:30}..." ``` ### 4. Frontend Origin'lerini Ekle #### Development: ```bash curl -X POST https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "origin": "http://localhost:3000", "description": "Local development" }' ``` #### Production (Next.js): ```bash curl -X POST https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "origin": "https://nextgo.beyhano.net.tr", "description": "Production Next.js frontend" }' ``` #### Staging (opsiyonel): ```bash curl -X POST https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "origin": "https://staging.beyhano.net.tr", "description": "Staging environment" }' ``` ### 5. Doğrulama ```bash # Whitelist'i kontrol et curl -X GET https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" | jq '.[] | {origin, is_active}' ``` **Beklenen Yanıt:** ```json [ { "origin": "https://nextgo.beyhano.net.tr", "is_active": true }, { "origin": "http://localhost:3000", "is_active": true } ] ``` --- ## 🧪 Test ### Frontend'den Test: ```javascript // Next.js veya React'ten fetch('https://goauth.beyhano.net.tr/v1/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'test@example.com', password: 'password123' }) }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => console.error(err)); ``` ### Browser Console'dan Test: ```javascript // Preflight request'i test et fetch('https://goauth.beyhano.net.tr/v1/auth/login', { method: 'OPTIONS', headers: { 'Access-Control-Request-Method': 'POST', 'Access-Control-Request-Headers': 'content-type' } }) .then(res => { console.log('Preflight Status:', res.status); // 204 olmalı console.log('CORS Headers:', res.headers); }); ``` --- ## 📊 CORS Headers Özeti Request başarılı olduğunda aşağıdaki header'lar dönmeli: ```http Access-Control-Allow-Origin: https://nextgo.beyhano.net.tr Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS Access-Control-Max-Age: 86400 ``` --- ## 🔒 Güvenlik Notları ### Whitelist Best Practices: ✅ **Yapın:** - Sadece güvendiğiniz domain'leri ekleyin - Her environment için ayrı origin kullanın - HTTPS kullanın (production için) - Description field'ını doldurun ❌ **Yapmayın:** - Wildcard (`*`) kullanmayın - HTTP kullanmayın (production'da) - Herkese açık domain eklemeyin - Test domain'lerini production'da bırakmayın ### Blacklist Kullanımı: Şüpheli veya kötü niyetli origin'leri blacklist'e ekleyin: ```bash curl -X POST https://goauth.beyhano.net.tr/v1/settings/cors/blacklist \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "origin": "https://malicious-site.com", "reason": "Security threat detected" }' ``` --- ## 🎯 Troubleshooting ### Hala 403 alıyorsanız: 1. **Whitelist'te var mı kontrol edin:** ```bash curl -X GET https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" | jq '.[] | .origin' ``` 2. **Origin tam eşleşiyor mu?** - ✅ `https://nextgo.beyhano.net.tr` (doğru) - ❌ `https://nextgo.beyhano.net.tr/` (slash yanlış) - ❌ `http://nextgo.beyhano.net.tr` (http/https farkı) 3. **is_active = true mi?** ```bash curl -X GET https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \ -H "Authorization: Bearer $TOKEN" | jq '.[] | {origin, is_active}' ``` 4. **Redis cache'i temizleyin:** ```bash docker exec -it gauth_redis redis-cli > DEL cors:whitelist > DEL cors:blacklist > exit ``` 5. **Container'ı restart edin:** ```bash docker restart app_auth_central ``` --- ## 📖 İlgili Dokümantasyon - **CORS API Detayları:** `CORS_API_DOCUMENTATION.md` - **Test Script:** `test-cors-api.sh` - **Deployment Guide:** `DOKPLOY_DEPLOYMENT.md` --- ## ✅ Checklist Production'a geçmeden önce: - [ ] Admin kullanıcı oluşturuldu - [ ] Production frontend origin whitelist'e eklendi - [ ] Development origin whitelist'e eklendi (opsiyonel) - [ ] Whitelist doğrulandı (GET request) - [ ] Frontend'den test edildi - [ ] OPTIONS preflight request test edildi - [ ] Browser console'da CORS hatası yok - [ ] Redis cache çalışıyor - [ ] Swagger'da CORS endpoints görünüyor **CORS 403 hatası çözüldü!** ✅