Next.js Authentication: NextAuth.js ve Clerk

Next.js Authentication: NextAuth.js ve Clerk
Kimlik doğrulama (authentication), web uygulamalarının en kritik bileşenlerinden biridir. Next.js ekosisteminde en popüler iki çözüm NextAuth.js (Auth.js) ve Clerk'tir. Bu yazıda her iki kütüphaneyi detaylı olarak inceleyecek, kurulumdan production'a kadar adım adım rehber sunacağız.
NextAuth.js (Auth.js) Nedir?
NextAuth.js, Next.js için açık kaynaklı bir authentication kütüphanesidir. OAuth, email/password, magic link ve daha birçok yöntemi destekler. v5 ile birlikte Auth.js adını almış ve framework-agnostik hale gelmiştir.
Kurulum
npm install next-auth@beta
# .env.local
AUTH_SECRET=your-secret-key-here
AUTH_GITHUB_ID=github-client-id
AUTH_GITHUB_SECRET=github-client-secret
AUTH_GOOGLE_ID=google-client-id
AUTH_GOOGLE_SECRET=google-client-secret
Temel Yapılandırma
// auth.js (proje kökünde)
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import Google from 'next-auth/providers/google';
import Credentials from 'next-auth/providers/credentials';
import { PrismaAdapter } from '@auth/prisma-adapter';
import { prisma } from '@/lib/prisma';
import bcrypt from 'bcryptjs';
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
GitHub,
Google,
Credentials({
name: 'E-posta ve Şifre',
credentials: {
email: { label: 'E-posta', type: 'email' },
password: { label: 'Şifre', type: 'password' },
},
async authorize(credentials) {
const user = await prisma.user.findUnique({
where: { email: credentials.email },
});
if (!user || !user.password) return null;
const isValid = await bcrypt.compare(
credentials.password,
user.password
);
return isValid ? user : null;
},
}),
],
callbacks: {
async session({ session, token }) {
if (token.sub) {
session.user.id = token.sub;
session.user.role = token.role;
}
return session;
},
async jwt({ token, user }) {
if (user) {
token.role = user.role;
}
return token;
},
},
pages: {
signIn: '/login',
error: '/auth/error',
},
});
Route Handler
// app/api/auth/[...nextauth]/route.js
import { handlers } from '@/auth';
export const { GET, POST } = handlers;
Middleware ile Koruma
// middleware.js
import { auth } from '@/auth';
export default auth((req) => {
const isLoggedIn = !!req.auth;
const isOnDashboard = req.nextUrl.pathname.startsWith('/dashboard');
const isOnLogin = req.nextUrl.pathname === '/login';
if (isOnDashboard && !isLoggedIn) {
return Response.redirect(new URL('/login', req.url));
}
if (isOnLogin && isLoggedIn) {
return Response.redirect(new URL('/dashboard', req.url));
}
});
export const config = {
matcher: ['/dashboard/:path*', '/login'],
};
Server Component'lerde Kullanım
// app/dashboard/page.js
import { auth } from '@/auth';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const session = await auth();
if (!session) {
redirect('/login');
}
return (
<div>
<h1>Hoş geldin, {session.user.name}!</h1>
<p>E-posta: {session.user.email}</p>
<img src={session.user.image} alt="Avatar" />
</div>
);
}
Login Sayfası
// app/login/page.js
import { signIn } from '@/auth';
export default function LoginPage() {
return (
<div className="login-container">
<h1>Giriş Yap</h1>
{/* OAuth butonları */}
<form action={async () => { 'use server'; await signIn('github'); }}>
<button type="submit">GitHub ile Giriş</button>
</form>
<form action={async () => { 'use server'; await signIn('google'); }}>
<button type="submit">Google ile Giriş</button>
</form>
<hr />
{/* Credentials formu */}
<form action={async (formData) => {
'use server';
await signIn('credentials', formData);
}}>
<input name="email" type="email" placeholder="E-posta" required />
<input name="password" type="password" placeholder="Şifre" required />
<button type="submit">Giriş Yap</button>
</form>
</div>
);
}
Clerk Nedir?
Clerk, tam yönetilen (fully managed) bir authentication ve kullanıcı yönetimi platformudur. Hazır UI bileşenleri, kullanıcı profil yönetimi, organizasyon desteği ve webhook'lar sunar.
Kurulum
npm install @clerk/nextjs
# .env.local
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
Provider Kurulumu
// app/layout.js
import { ClerkProvider } from '@clerk/nextjs';
import { trTR } from '@clerk/localizations';
export default function RootLayout({ children }) {
return (
<ClerkProvider localization={trTR}>
<html lang="tr">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
Middleware
// middleware.js
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isProtectedRoute = createRouteMatcher([
'/dashboard(.*)',
'/settings(.*)',
'/api/private(.*)',
]);
export default clerkMiddleware(async (auth, req) => {
if (isProtectedRoute(req)) {
await auth.protect();
}
});
export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
Hazır UI Bileşenleri
import {
SignInButton,
SignUpButton,
SignedIn,
SignedOut,
UserButton,
} from '@clerk/nextjs';
function Header() {
return (
<header>
<nav>
<SignedOut>
<SignInButton mode="modal" />
<SignUpButton mode="modal" />
</SignedOut>
<SignedIn>
<UserButton
appearance={{
elements: { avatarBox: 'w-10 h-10' },
}}
afterSignOutUrl="/"
/>
</SignedIn>
</nav>
</header>
);
}
Server Component'lerde Clerk
import { currentUser, auth } from '@clerk/nextjs/server';
export default async function ProfilePage() {
const user = await currentUser();
const { userId, orgId } = await auth();
if (!user) return <p>Giriş yapmanız gerekiyor.</p>;
return (
<div>
<h1>{user.firstName} {user.lastName}</h1>
<p>{user.emailAddresses[0].emailAddress}</p>
<img src={user.imageUrl} alt="Profil" />
</div>
);
}
Karşılaştırma
| Özellik | NextAuth.js | Clerk |
|---|---|---|
| Fiyat | Ücretsiz (açık kaynak) | Freemium (10K MAU ücretsiz) |
| Barındırma | Self-hosted | Managed service |
| UI Bileşenleri | Kendiniz yazarsınız | Hazır bileşenler |
| Kullanıcı Yönetimi | Kendiniz yaparsınız | Dashboard var |
| Veritabanı | Kendi veritabanınız | Clerk yönetir |
| Özelleştirme | Tam kontrol | Tema ile sınırlı |
| Organizasyon | Manuel | Yerleşik destek |
Sonuç
Next.js'te authentication için NextAuth.js ve Clerk iki güçlü seçenektir. NextAuth.js, açık kaynak ve self-hosted yapısıyla tam kontrol sunarken, Clerk managed bir servis olarak hızlı kurulum ve hazır bileşenler sağlar. Her iki çözüm de middleware tabanlı route koruması, Server Component desteği ve modern Next.js App Router uyumluluğu sunar. Projenizin ihtiyaçlarına, bütçenize ve kontrol gereksiniminize göre doğru çözümü seçebilirsiniz.