Clerk ile Authentication: 10 Dakikada Kullanıcı Yönetimi
Authentication, her web uygulamasının temel taşıdır — ama aynı zamanda geliştiricilerin en çok vakit kaybettiği alanlardan biridir. Şifre hashleme, session yönetimi, OAuth entegrasyonları, e-posta doğrulama, iki faktörlü kimlik doğrulama... Liste uzayıp gider. Peki ya tüm bunları 10 dakikada çözebileceğinizi söylesem?
Bu yazıda Clerk kullanarak bir React (Next.js) uygulamasına profesyonel düzeyde authentication sistemi eklemeyi adım adım göstereceğim. Sıfırdan başlayıp, korumalı sayfalar, kullanıcı profil yönetimi ve webhook entegrasyonuna kadar ilerleyeceğiz.
Clerk Nedir ve Neden Tercih Edilmeli?
Clerk, modern web uygulamaları için geliştirilmiş bir authentication ve kullanıcı yönetimi platformudur. Firebase Auth, Auth0 veya NextAuth gibi alternatiflerin aksine Clerk, özellikle developer experience (DX) konusunda öne çıkar.
Clerk'ün Öne Çıkan Özellikleri
- Hazır UI bileşenleri:
<SignIn />,<SignUp />,<UserButton />gibi bileşenlerle saniyeler içinde kullanıcı arayüzü - Çoklu giriş yöntemleri: E-posta, Google, GitHub, Apple ve daha fazla OAuth sağlayıcı
- Multi-session desteği: Kullanıcılar birden fazla hesapla aynı anda oturum açabilir
- Organization yönetimi: Takım ve organizasyon bazlı erişim kontrolü
- Webhook desteği: Kullanıcı olaylarını backend'inize aktarma
- Edge-ready: Middleware seviyesinde authentication kontrolü
- Ücretsiz plan: 10.000 aylık aktif kullanıcıya kadar ücretsiz
Adım 1: Proje Kurulumu
Öncelikle bir Next.js projesi oluşturalım ve Clerk paketini yükleyelim:
npx create-next-app@latest clerk-auth-demo --typescript --tailwind --app
cd clerk-auth-demo
npm install @clerk/nextjsClerk Dashboard'da Uygulama Oluşturma
- clerk.com adresine gidin ve ücretsiz hesap oluşturun
- Dashboard'da "Create Application" butonuna tıklayın
- Uygulamanıza bir isim verin (örn: "My Auth Demo")
- Desteklemek istediğiniz giriş yöntemlerini seçin (Email, Google, GitHub vb.)
- "Create Application" ile onaylayın
Dashboard'dan API anahtarlarınızı alın ve projenizin kök dizininde .env.local dosyası oluşturun:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxxxxxxxxxxxxxx
CLERK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxxxxAdım 2: Clerk Provider Yapılandırması
Clerk'ün tüm uygulamanızda çalışabilmesi için ClerkProvider ile sarmalama yapmanız gerekiyor. app/layout.tsx dosyasını güncelleyin:
// app/layout.tsx
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { ClerkProvider } from '@clerk/nextjs'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Clerk Auth Demo',
description: '10 dakikada authentication',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<ClerkProvider>
<html lang="tr">
<body className={inter.className}>{children}</body>
</html>
</ClerkProvider>
)
}Bu kadar! Clerk artık uygulamanızın her yerinde kullanılabilir durumda.
Adım 3: Middleware ile Route Koruması
Clerk'ün en güçlü özelliklerinden biri middleware seviyesinde authentication kontrolüdür. Proje kök dizininde middleware.ts dosyası oluşturun:
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isPublicRoute = createRouteMatcher([
'/',
'/sign-in(.*)',
'/sign-up(.*)',
'/api/webhooks(.*)',
])
export default clerkMiddleware(async (auth, request) => {
if (!isPublicRoute(request)) {
await auth.protect()
}
})
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
'/(api|trpc)(.*)',
],
}Bu yapılandırma ile:
- Ana sayfa (
/), giriş ve kayıt sayfaları herkese açık - Diğer tüm sayfalar authentication gerektirir
- Giriş yapmamış kullanıcılar otomatik olarak sign-in sayfasına yönlendirilir
Adım 4: Giriş ve Kayıt Sayfaları
Clerk'ün hazır bileşenleriyle giriş ve kayıt sayfalarını oluşturmak inanılmaz kolaydır:
// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs'
export default function SignInPage() {
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<SignIn
appearance={{
elements: {
rootBox: 'mx-auto',
card: 'shadow-xl',
},
}}
/>
</div>
)
}// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs'
export default function SignUpPage() {
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<SignUp
appearance={{
elements: {
rootBox: 'mx-auto',
card: 'shadow-xl',
},
}}
/>
</div>
)
}Ardından .env.local dosyasına yönlendirme URL'lerini ekleyin:
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-upTarayıcınızda /sign-in adresine gittiğinizde, Google, GitHub ve e-posta ile giriş seçeneklerini içeren profesyonel bir giriş formu göreceksiniz — tek satır CSS yazmadan.
Adım 5: Ana Sayfa ve Kullanıcı Durumu
Artık kullanıcının giriş yapıp yapmadığına göre farklı içerik gösterebiliriz:
// app/page.tsx
import { SignedIn, SignedOut, UserButton } from '@clerk/nextjs'
import { currentUser } from '@clerk/nextjs/server'
import Link from 'next/link'
export default async function HomePage() {
const user = await currentUser()
return (
<div className="min-h-screen bg-gray-50">
<nav className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 py-3 flex justify-between items-center">
<h1 className="text-xl font-bold text-gray-900">🔐 Auth Demo</h1>
<SignedIn>
<div className="flex items-center gap-4">
<Link
href="/dashboard"
className="text-gray-600 hover:text-gray-900"
>
Dashboard
</Link>
<UserButton afterSignOutUrl="/" />
</div>
</SignedIn>
<SignedOut>
<div className="flex gap-3">
<Link
href="/sign-in"
className="px-4 py-2 text-gray-700 hover:text-gray-900"
>
Giriş Yap
</Link>
<Link
href="/sign-up"
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Kayıt Ol
</Link>
</div>
</SignedOut>
</div>
</nav>
<main className="max-w-4xl mx-auto px-4 py-16 text-center">
<SignedIn>
<h2 className="text-3xl font-bold mb-4">
Hoş geldin, {user?.firstName}! 👋
</h2>
<p className="text-gray-600">
Başarıyla giriş yaptın. Dashboard'a gidebilirsin.
</p>
</SignedIn>
<SignedOut>
<h2 className="text-4xl font-bold mb-4">
10 Dakikada Authentication
</h2>
<p className="text-gray-600 text-lg">
Clerk ile modern, güvenli ve hızlı kullanıcı yönetimi.
</p>
</SignedOut>
</main>
</div>
)
}Burada dikkat çekici birkaç önemli konsept var:
<SignedIn>: Yalnızca giriş yapmış kullanıcılara gösterilir<SignedOut>: Yalnızca giriş yapmamış kullanıcılara gösterilir<UserButton />: Profil fotoğrafı, hesap yönetimi ve çıkış butonu içeren hazır bileşencurrentUser(): Sunucu tarafında kullanıcı bilgilerine erişim
Adım 6: Korumalı Dashboard Sayfası
Middleware sayesinde /dashboard route'u zaten korunuyor. Şimdi kullanıcı bilgilerini gösteren bir dashboard oluşturalım:
// app/dashboard/page.tsx
import { currentUser } from '@clerk/nextjs/server'
import { UserProfile } from '@clerk/nextjs'
import { redirect } from 'next/navigation'
export default async function DashboardPage() {
const user = await currentUser()
if (!user) {
redirect('/sign-in')
}
return (
<div className="max-w-6xl mx-auto px-4 py-8">
<h1 className="text-3xl font-bold mb-8">Dashboard</h1>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
<div className="bg-white p-6 rounded-xl shadow-sm border">
<h3 className="text-sm text-gray-500 mb-1">Ad Soyad</h3>
<p className="text-lg font-semibold">
{user.firstName} {user.lastName}
</p>
</div>
<div className="bg-white p-6 rounded-xl shadow-sm border">
<h3 className="text-sm text-gray-500 mb-1">E-posta</h3>
<p className="text-lg font-semibold">
{user.emailAddresses[0]?.emailAddress}
</p>
</div>
<div className="bg-white p-6 rounded-xl shadow-sm border">
<h3 className="text-sm text-gray-500 mb-1">Kayıt Tarihi</h3>
<p className="text-lg font-semibold">
{new Date(user.createdAt).toLocaleDateString('tr-TR')}
</p>
</div>
</div>
<div className="bg-white rounded-xl shadow-sm border p-6">
<h2 className="text-xl font-bold mb-4">Profil Ayarları</h2>
<UserProfile
appearance={{
elements: {
rootBox: 'w-full',
card: 'shadow-none border-0',
},
}}
/>
</div>
</div>
)
}<UserProfile /> bileşeni kullanıcıya şu imkânları verir:
- Profil fotoğrafı güncelleme
- İsim ve e-posta değiştirme
- Şifre güncelleme
- Bağlı hesapları yönetme (Google, GitHub vb.)
- İki faktörlü kimlik doğrulama ayarlama
- Aktif oturumları görüntüleme ve sonlandırma
Tüm bunlar tek bir bileşen ile!
Adım 7: API Route'larında Authentication
Sunucu tarafında API route'larınızı da korumak son derece kolaydır:
// app/api/user/route.ts
import { auth, currentUser } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
export async function GET() {
const { userId } = await auth()
if (!userId) {
return NextResponse.json(
{ error: 'Yetkisiz erişim' },
{ status: 401 }
)
}
const user = await currentUser()
return NextResponse.json({
id: user?.id,
email: user?.emailAddresses[0]?.emailAddress,
name: `${user?.firstName} ${user?.lastName}`,
imageUrl: user?.imageUrl,
})
}Adım 8: Client-Side Hook'lar
Client component'larda kullanıcı bilgilerine erişmek için Clerk'ün hook'larını kullanabilirsiniz:
'use client'
import { useUser, useAuth } from '@clerk/nextjs'
export function WelcomeBanner() {
const { user, isLoaded, isSignedIn } = useUser()
const { signOut, getToken } = useAuth()
if (!isLoaded) {
return <div className="animate-pulse h-20 bg-gray-200 rounded-lg" />
}
if (!isSignedIn) {
return null
}
const handleApiCall = async () => {
const token = await getToken()
const response = await fetch('/api/protected-endpoint', {
headers: {
Authorization: `Bearer ${token}`,
},
})
const data = await response.json()
console.log(data)
}
return (
<div className="bg-blue-50 border border-blue-200 rounded-lg p-6">
<div className="flex items-center gap-4">
<img
src={user.imageUrl}
alt={user.fullName || 'Kullanıcı'}
className="w-12 h-12 rounded-full"
/>
<div>
<h3 className="font-semibold text-blue-900">
Merhaba, {user.firstName}!
</h3>
<p className="text-sm text-blue-700">
{user.emailAddresses[0]?.emailAddress}
</p>
</div>
</div>
<button
onClick={handleApiCall}
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg text-sm"
>
API'yi Test Et
</button>
</div>
)
}Öne çıkan hook'lar:
useUser(): Kullanıcı bilgilerine erişimuseAuth(): Authentication durumu, token alma, çıkış yapmauseSignIn(): Özel giriş akışları oluşturmauseSignUp(): Özel kayıt akışları oluşturmauseOrganization(): Organizasyon yönetimi
Bonus: Tema Özelleştirme
Clerk bileşenlerinin görünümünü uygulamanızın tasarımına uydurmak için appearance prop'unu kullanabilirsiniz:
// app/layout.tsx
<ClerkProvider
appearance={{
variables: {
colorPrimary: '#6366f1',
colorBackground: '#ffffff',
borderRadius: '0.75rem',
fontFamily: 'Inter, sans-serif',
},
elements: {
formButtonPrimary:
'bg-indigo-600 hover:bg-indigo-700 text-sm font-medium',
card: 'shadow-lg border border-gray-200',
headerTitle: 'text-gray-900 font-bold',
socialButtonsBlockButton:
'border-gray-300 hover:bg-gray-50 font-medium',
},
}}
>Clerk vs Alternatifler: Hızlı Karşılaştırma
| Özellik | Clerk | NextAuth | Firebase Auth | Auth0 |
|---|---|---|---|---|
| Hazır UI bileşenleri | ✅ | ❌ | ❌ | ✅ |
| Ücretsiz plan limiti | 10K MAU | Sınırsız | 50K MAU | 7.5K MAU |
| Kurulum süresi | ~10 dk | ~30 dk | ~20 dk | ~30 dk |
| Multi-session | ✅ | ❌ | ❌ | ❌ |
| Organization desteği | ✅ | ❌ | ❌ | ✅ |
| Edge Runtime | ✅ | Kısıtlı | ❌ | ❌ |
| Webhook'lar | ✅ | Kısıtlı | ✅ | ✅ |
Sık Yapılan Hatalar ve İpuçları
Environment variable'ları kontrol edin:
NEXT_PUBLIC_prefix'i olmayan key'ler client tarafında çalışmaz.Middleware matcher'ı doğru yapılandırın: Statik dosyaları (CSS, JS, resimler) matcher'dan hariç tutmayı unutmayın, aksi halde performans sorunları yaşarsınız.
currentUser()vsauth():currentUser()tam kullanıcı objesini döner ama ek bir API çağrısı yapar. SadeceuserIdyeterliyseauth()tercih edin.Webhook'larda imza doğrulama: Clerk webhook'larını kullanıyorsanız,
svixkütüphanesi ile imza doğrulaması yapmayı atlamamayın.Development ve production key'leri karıştırmayın: Clerk'ün test ve production ortamları farklı key'ler kullanır.
Sonuç
Clerk, modern web uygulamalarında authentication sorununu kökten çözen bir araçtır. Bu yazıda gördüğünüz gibi, gerçekten 10 dakikadan kısa bir sürede:
- ✅ Kullanıcı kayıt ve giriş sistemi
- ✅ Google/GitHub ile sosyal giriş
- ✅ Korumalı route'lar (middleware seviyesinde)
- ✅ Profil yönetimi sayfası
- ✅ API route koruması
- ✅ Client-side authentication hook'ları
kurmuş olduk. Clerk'ün sunduğu hazır bileşenler ve basit API sayesinde, authentication altyapısına saatler harcamak yerine asıl ürününüze odaklanabilirsiniz.
Eğer yeni bir projeye başlıyorsanız veya mevcut projenizin authentication sistemini modernleştirmek istiyorsanız, Clerk kesinlikle değerlendirmeniz gereken bir seçenek. Ücretsiz planı çoğu proje için yeterli olacaktır ve ölçeklendikçe büyüme planları da makul fiyatlandırma sunuyor.
Artık "authentication zor" bahanesi geçerli değil — Clerk ile 10 dakikada işinizi bitirin. 🚀