# Clerk JWT Authentication Fix - Supabase RLS Uyumluluğu

## 🔴 Problem

Clerk'in generic JWT'si Supabase tarafından **authenticated** role olarak tanınmıyor. Supabase, sadece kendi JWT secret'ı ile imzalanmış token'ları authenticated sayar. Clerk'in generic token'ı farklı bir key ile imzalı olduğu için, tüm RLS politikaları (profiles INSERT/UPDATE dahil) çalışmıyor.

### Sorunun Nedeni

1. **Clerk Token**: Clerk kendi secret key'i ile JWT imzalar
2. **Supabase Beklentisi**: Supabase kendi JWT secret'ı ile imzalanmış token bekler
3. **Sonuç**: Clerk token'ı `anon` role olarak kabul edilir, `authenticated` role'üne bağlı politikalar çalışmaz

## ✅ Çözüm

### 1. Kısa Vadeli Çözüm (Uygulandı)

RLS politikalarını hem `anon` hem `authenticated` role'leri için çalışacak şekilde güncelledik:

#### Migration 00093: Profiles INSERT Policy
```sql
CREATE POLICY "Allow profile creation with clerk_user_id"
  ON profiles FOR INSERT
  TO public
  WITH CHECK (
    clerk_user_id IS NOT NULL
    AND clerk_user_id <> ''
    AND email IS NOT NULL
  );
```

**Güvenlik Kontrolleri:**
- ✅ `clerk_user_id` boş olamaz
- ✅ `email` zorunlu
- ✅ Rastgele insert önlenir
- ✅ Hem anon hem authenticated çalışır

#### Migration 00094: Profiles UPDATE Policy
```sql
CREATE POLICY "Allow profile update with email match"
  ON profiles FOR UPDATE
  TO public
  USING (
    email IS NOT NULL
    AND (clerk_user_id IS NULL OR clerk_user_id = '')
  )
  WITH CHECK (
    clerk_user_id IS NOT NULL
    AND clerk_user_id <> ''
  );
```

**Güvenlik Kontrolleri:**
- ✅ Sadece henüz bağlanmamış profiller güncellenebilir
- ✅ Email zorunlu
- ✅ Güncelleme sonrası clerk_user_id dolu olmalı
- ✅ Email ile profil eşleştirme güvenli

### 2. Uzun Vadeli Çözüm (Önerilen)

Clerk Dashboard'da **Supabase JWT Template** oluşturun:

#### Adım 1: Clerk Dashboard'a Gidin
1. [Clerk Dashboard](https://dashboard.clerk.com) → Projenizi seçin
2. **JWT Templates** → **New Template**

#### Adım 2: Supabase Template Oluşturun
```json
{
  "name": "supabase",
  "claims": {
    "aud": "authenticated",
    "exp": "{{user.created_at + 3600}}",
    "sub": "{{user.id}}",
    "email": "{{user.primary_email_address}}",
    "app_metadata": {
      "provider": "clerk"
    },
    "user_metadata": {
      "full_name": "{{user.first_name}} {{user.last_name}}",
      "avatar_url": "{{user.image_url}}"
    }
  },
  "lifetime": 3600,
  "signing_key": "YOUR_SUPABASE_JWT_SECRET"
}
```

#### Adım 3: Supabase JWT Secret'ı Alın
1. [Supabase Dashboard](https://supabase.com/dashboard) → Projenizi seçin
2. **Settings** → **API** → **JWT Settings**
3. **JWT Secret** değerini kopyalayın

#### Adım 4: Template'i Kaydedin
- Template adı: `supabase`
- Signing key: Supabase JWT Secret
- Lifetime: 3600 (1 saat)

#### Adım 5: Kod Güncellemesi (Zaten Mevcut)
`useAuth.ts` dosyasında zaten template desteği var:

```typescript
const token = await getToken({ template: 'supabase' });
```

## 🔍 Nasıl Çalışır?

### Şu Anki Durum (Kısa Vadeli Çözüm)
```
User Login → Clerk Generic JWT → Supabase (anon role)
                                    ↓
                        RLS Policy (public role)
                                    ↓
                        ✅ Profile Created/Updated
```

### JWT Template Sonrası (Uzun Vadeli Çözüm)
```
User Login → Clerk Supabase JWT → Supabase (authenticated role)
                                      ↓
                          RLS Policy (authenticated role)
                                      ↓
                          ✅ Profile Created/Updated
```

## 🛡️ Güvenlik

### Kısa Vadeli Çözüm Güvenliği
- ✅ **clerk_user_id zorunlu**: Rastgele insert önlenir
- ✅ **email zorunlu**: Kimlik doğrulama gerekli
- ✅ **UPDATE kısıtlaması**: Sadece bağlanmamış profiller güncellenebilir
- ✅ **WITH CHECK**: Güncelleme sonrası clerk_user_id dolu olmalı

### Uzun Vadeli Çözüm Güvenliği
- ✅ **Supabase JWT Secret**: Token Supabase tarafından doğrulanır
- ✅ **authenticated role**: Tüm RLS politikaları normal çalışır
- ✅ **Token expiration**: 1 saatlik geçerlilik süresi
- ✅ **Clerk verification**: Token Clerk tarafından imzalanır

## 📊 Test Senaryoları

### Test 1: Yeni Kullanıcı Kaydı
```typescript
// 1. Clerk'e kayıt ol
const { user } = await clerk.signUp({ email, password });

// 2. useAuth hook otomatik profil oluşturur
// ✅ INSERT policy çalışır (anon role)
// ✅ clerk_user_id ve email dolu
// ✅ Profile başarıyla oluşturulur
```

### Test 2: Mevcut Profil Bağlama
```typescript
// 1. Email ile profil var (clerk_user_id boş)
// 2. Clerk'e giriş yap
const { user } = await clerk.signIn({ email, password });

// 3. useAuth hook profili bulur ve bağlar
// ✅ UPDATE policy çalışır (anon role)
// ✅ clerk_user_id güncellenir
// ✅ Profile başarıyla bağlanır
```

### Test 3: JWT Template ile Giriş
```typescript
// 1. JWT Template kurulu
// 2. Clerk'e giriş yap
const token = await getToken({ template: 'supabase' });

// 3. Token authenticated role ile gelir
// ✅ Tüm RLS politikaları normal çalışır
// ✅ authenticated role özellikleri kullanılabilir
```

## 🔧 Troubleshooting

### Problem: Profile oluşturulamıyor
**Çözüm:**
1. Migration 00093 uygulandı mı kontrol edin
2. `clerk_user_id` ve `email` değerleri dolu mu kontrol edin
3. Console'da hata mesajlarını kontrol edin

### Problem: Profile güncellenemiyor
**Çözüm:**
1. Migration 00094 uygulandı mı kontrol edin
2. Profile'da `clerk_user_id` boş mu kontrol edin
3. Email eşleşmesi doğru mu kontrol edin

### Problem: JWT Template çalışmıyor
**Çözüm:**
1. Template adı `supabase` olmalı
2. Supabase JWT Secret doğru mu kontrol edin
3. Template lifetime 3600 olmalı
4. `getToken({ template: 'supabase' })` kullanıldığından emin olun

## 📝 Notlar

### Clerk Webhook
- ✅ Webhook **service role** kullanır
- ✅ RLS politikalarından etkilenmez
- ✅ Değişiklik gerektirmez

### useAuth Hook
- ✅ Fallback mekanizması mevcut
- ✅ Template yoksa generic token kullanır
- ✅ Her iki durumda da çalışır

### Admin Kullanıcılar
- ✅ Admin politikaları ayrı
- ✅ `is_admin()` fonksiyonu kullanır
- ✅ Değişiklik gerektirmez

## 🎯 Sonuç

### Şu Anki Durum
- ✅ Profile oluşturma çalışıyor (anon role)
- ✅ Profile güncelleme çalışıyor (anon role)
- ✅ Güvenlik korunuyor
- ✅ Kullanıcı deneyimi kesintisiz

### Önerilen Adım
- 📌 Clerk Dashboard'da Supabase JWT Template oluşturun
- 📌 Uzun vadeli çözüm için daha güvenli
- 📌 authenticated role özellikleri kullanılabilir
- 📌 Tüm RLS politikaları normal çalışır

## 📚 Referanslar

- [Clerk JWT Templates](https://clerk.com/docs/backend-requests/making/jwt-templates)
- [Supabase RLS](https://supabase.com/docs/guides/auth/row-level-security)
- [Clerk + Supabase Integration](https://clerk.com/docs/integrations/databases/supabase)
