İçeriğe geç
Sedat Demir
Geri dön

Clerk ile Authentication: 10 Dakikada Kullanıcı Yönetimi

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


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/nextjs

Clerk Dashboard'da Uygulama Oluşturma

  1. clerk.com adresine gidin ve ücretsiz hesap oluşturun
  2. Dashboard'da "Create Application" butonuna tıklayın
  3. Uygulamanıza bir isim verin (örn: "My Auth Demo")
  4. Desteklemek istediğiniz giriş yöntemlerini seçin (Email, Google, GitHub vb.)
  5. "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_xxxxxxxxxxxxxxxxxxxxxxxx

Adı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:


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-up

Tarayı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:


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:

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:


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ı

  1. Environment variable'ları kontrol edin: NEXT_PUBLIC_ prefix'i olmayan key'ler client tarafında çalışmaz.

  2. 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.

  3. currentUser() vs auth(): currentUser() tam kullanıcı objesini döner ama ek bir API çağrısı yapar. Sadece userId yeterliyse auth() tercih edin.

  4. Webhook'larda imza doğrulama: Clerk webhook'larını kullanıyorsanız, svix kütüphanesi ile imza doğrulaması yapmayı atlamamayın.

  5. 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:

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. 🚀


Share this post on:

Sonraki Yazı
Hono + Cloudflare Workers + D1: Edge'de Tam Yığın Uygulama Geliştirme Rehberi