38980-vm/app-9w9pd00g5j41/CLERK_JWT_FIX.md
2026-03-04 18:25:09 +00:00

232 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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