Supabase Auth ile React'te Kullanıcı Yönetimi: Kayıt, Giriş ve Rol Sistemi
Supabase Auth ile React'te kullanıcı kaydı, giriş, oturum yönetimi ve rol bazlı yetkilendirme nasıl yapılır? Protected routes, onAuthStateChange ve...
Sorun: “Kullanıcı Girişi Nasıl Yapılır?”
Her web uygulamasının ilk ihtiyacı: kullanıcı kaydı, giriş, çıkış ve oturum yönetimi. Supabase Auth bunu 5 dakikada çözer — ama production’da doğru yapılması gerekir.
Supabase Client Kurulumu
npm install @supabase/supabase-js
// src/lib/supabase.ts
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
export const supabase = createClient(supabaseUrl, supabaseAnonKey);
⚠️
VITE_prefix’i client-side’da erişilebilir yapar.service_rolekey’ini asla client’a koymayın.
Auth Context — Global Oturum Yönetimi
// src/contexts/AuthContext.tsx
import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { Session, User } from '@supabase/supabase-js';
import { supabase } from '../lib/supabase';
interface AuthContextType {
session: Session | null;
user: User | null;
loading: boolean;
signUp: (email: string, password: string) => Promise<void>;
signIn: (email: string, password: string) => Promise<void>;
signOut: () => Promise<void>;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export function AuthProvider({ children }: { children: ReactNode }) {
const [session, setSession] = useState<Session | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// 1. Mevcut oturumu al
supabase.auth.getSession().then(({ data: { session } }) => {
setSession(session);
setLoading(false);
});
// 2. Oturum değişikliklerini dinle
const { data: { subscription } } = supabase.auth.onAuthStateChange(
(_event, session) => {
setSession(session);
}
);
// 3. Cleanup
return () => subscription.unsubscribe();
}, []);
const signUp = async (email: string, password: string) => {
const { error } = await supabase.auth.signUp({ email, password });
if (error) throw error;
};
const signIn = async (email: string, password: string) => {
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error) throw error;
};
const signOut = async () => {
const { error } = await supabase.auth.signOut();
if (error) throw error;
};
return (
<AuthContext.Provider value={{
session,
user: session?.user ?? null,
loading,
signUp,
signIn,
signOut,
}}>
{children}
</AuthContext.Provider>
);
}
export function useAuth() {
const context = useContext(AuthContext);
if (!context) throw new Error('useAuth must be used within AuthProvider');
return context;
}
Kullanım: Giriş Formu
// src/components/LoginForm.tsx
import { useState } from 'react';
import { useAuth } from '../contexts/AuthContext';
export function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const { signIn } = useAuth();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
try {
await signIn(email, password);
// Başarılı — onAuthStateChange otomatik günceller
} catch (err: any) {
setError(err.message);
}
};
return (
<form onSubmit={handleSubmit}>
<input type="email" value={email}
onChange={e => setEmail(e.target.value)}
placeholder="E-posta" required />
<input type="password" value={password}
onChange={e => setPassword(e.target.value)}
placeholder="Şifre" required />
{error && <p style={{ color: 'red' }}>{error}</p>}
<button type="submit">Giriş Yap</button>
</form>
);
}
Protected Routes (Korumalı Sayfalar)
Giriş yapmamış kullanıcıları login sayfasına yönlendirin:
// src/components/ProtectedRoute.tsx
import { Navigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
export function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { session, loading } = useAuth();
if (loading) return <div>Yükleniyor...</div>;
if (!session) return <Navigate to="/login" replace />;
return <>{children}</>;
}
// App.tsx
<AuthProvider>
<Routes>
<Route path="/login" element={<LoginForm />} />
<Route path="/dashboard" element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
} />
</Routes>
</AuthProvider>
Rol Sistemi: user_metadata vs app_metadata
Supabase’de roller iki yerde saklanabilir:
| Alan | Kim değiştirebilir? | Kullanım |
|---|---|---|
user_metadata | Kullanıcı kendisi | Profil bilgileri |
app_metadata | Sadece backend (service_role) | Roller ve yetkiler |
-- Kullanıcıya admin rolü atama (Supabase SQL Editor)
UPDATE auth.users
SET raw_app_meta_data = raw_app_meta_data || '{"role": "admin"}'::jsonb
WHERE email = 'admin@example.com';
// React'te rol kontrolü
const { user } = useAuth();
const role = user?.app_metadata?.role || 'viewer';
if (role !== 'admin') {
return <p>Bu sayfaya erişim yetkiniz yok.</p>;
}
RLS ile Auth Entegrasyonu
Supabase Auth + RLS birlikte kullanıldığında güvenlik veritabanı seviyesine iner:
-- Kullanıcı sadece kendi verilerini görsün
CREATE POLICY "Users see own data" ON user_notes
FOR SELECT
USING (user_id = auth.uid());
-- Admin her şeyi görsün
CREATE POLICY "Admins see all" ON user_notes
FOR SELECT
USING (
(auth.jwt() -> 'app_metadata' ->> 'role') = 'admin'
);
onAuthStateChange Event’leri
onAuthStateChange şu eventleri yakalar:
| Event | Ne Zaman? |
|---|---|
SIGNED_IN | Kullanıcı giriş yaptı |
SIGNED_OUT | Kullanıcı çıkış yaptı |
TOKEN_REFRESHED | JWT token yenilendi |
USER_UPDATED | Kullanıcı bilgileri güncellendi |
PASSWORD_RECOVERY | Şifre sıfırlama linki tıklandı |
Dikkat Edilecekler
loadingstate’i: İlk render’dagetSession()tamamlanmadan Protected Route yönlendirme yapmamalı.- Token refresh: Supabase otomatik yapar ama
onAuthStateChangedinlemelisiniz. anonkey güvenliği: Client-side’da güvenle kullanılabilir — RLS ile korunur.- Şifre politikası: Supabase varsayılan minimum 6 karakter. Dashboard’dan değiştirilebilir.
İlgili Yazılar
- Supabase RLS Yetkilendirme — 9 rol, 8 şube RLS
- SECURITY DEFINER vs INVOKER — Fonksiyon güvenliği
- .env Güvenli Yönetimi — Key sızıntısı önleme
- React Query + Supabase Cache — Auth + data cache
Bu rehber Supabase Auth Docs ve React Context API dokümantasyonuna dayanarak hazırlanmıştır.