first commit
This commit is contained in:
356
CORS_403_FIX.md
Normal file
356
CORS_403_FIX.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# 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ü!** ✅
|
||||
Reference in New Issue
Block a user