Files
atahango/belgeler/CORS_403_FIX.md
Beyhan Oğur bbbf76b184 first commit
2026-04-26 21:35:24 +03:00

8.4 KiB
Raw Permalink Blame History

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):

// Hardcoded CORS - sadece localhost
r.Use(cors.New(cors.Config{
    AllowOrigins: []string{"http://localhost:3000"},
    ...
}))

Sonra (main.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:

# 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:

{
  "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 gelirOrigin 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):

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:

docker exec -it app_auth_central sh

2. Admin Kullanıcı Oluştur

./main seed-admin

Credentials:

  • Email: admin@gauth.local
  • Password: Admin@123

3. Admin Login (Local veya cURL)

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:

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):

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):

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

# 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:

[
  {
    "origin": "https://nextgo.beyhano.net.tr",
    "is_active": true
  },
  {
    "origin": "http://localhost:3000",
    "is_active": true
  }
]

🧪 Test

Frontend'den Test:

// 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:

// 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:

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:

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:
curl -X GET https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \
  -H "Authorization: Bearer $TOKEN" | jq '.[] | .origin'
  1. 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ı)
  2. is_active = true mi?

curl -X GET https://goauth.beyhano.net.tr/v1/settings/cors/whitelist \
  -H "Authorization: Bearer $TOKEN" | jq '.[] | {origin, is_active}'
  1. Redis cache'i temizleyin:
docker exec -it gauth_redis redis-cli
> DEL cors:whitelist
> DEL cors:blacklist
> exit
  1. Container'ı restart edin:
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ü!