Clerk Authentication
Battle-tested patterns for Clerk authentication in Next.js applications.
Overview#
Clerk provides a complete authentication solution with:
- Pre-built UI components
- Social login providers
- Multi-factor authentication
- User management dashboard
- Webhook support
Prerequisites:
- Clerk account and API keys
- Next.js 14+ with App Router
Installation#
npm install @clerk/nextjs1# .env.local
2NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
3CLERK_SECRET_KEY=sk_test_...
4NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
5NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
6NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
7NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboardImplementation#
Server-Side Auth Check#
1// lib/auth.ts
2import { auth } from '@clerk/nextjs/server'
3
4export async function requireAuth() {
5 const { userId } = await auth()
6
7 if (!userId) {
8 throw new Error('UNAUTHORIZED')
9 }
10
11 return userId
12}
13
14// Usage in Server Action
15export async function myAction() {
16 const userId = await requireAuth()
17 // Continue with authenticated user
18}Protected Layout#
1// app/(protected)/layout.tsx
2import { auth } from '@clerk/nextjs/server'
3import { redirect } from 'next/navigation'
4
5export default async function ProtectedLayout({
6 children
7}: {
8 children: React.ReactNode
9}) {
10 const { userId } = await auth()
11
12 if (!userId) {
13 redirect('/sign-in')
14 }
15
16 return <>{children}</>
17}Get Current User with Metadata#
1// lib/auth.ts
2import { currentUser } from '@clerk/nextjs/server'
3import { prisma } from '@/lib/db'
4
5export async function getCurrentUser() {
6 const user = await currentUser()
7 if (!user) return null
8
9 // Get or create database user
10 const dbUser = await prisma.user.upsert({
11 where: { clerkId: user.id },
12 update: {
13 email: user.emailAddresses[0]?.emailAddress,
14 name: `${user.firstName} ${user.lastName}`.trim()
15 },
16 create: {
17 clerkId: user.id,
18 email: user.emailAddresses[0]?.emailAddress ?? '',
19 name: `${user.firstName} ${user.lastName}`.trim()
20 }
21 })
22
23 return dbUser
24}Client-Side Auth Hook#
1// hooks/use-user.ts
2'use client'
3import { useUser } from '@clerk/nextjs'
4
5export function useCurrentUser() {
6 const { user, isLoaded, isSignedIn } = useUser()
7
8 return {
9 user: isSignedIn ? user : null,
10 isLoading: !isLoaded,
11 isAuthenticated: isSignedIn
12 }
13}Middleware Configuration#
1// middleware.ts
2import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
3
4const isProtectedRoute = createRouteMatcher([
5 '/dashboard(.*)',
6 '/settings(.*)',
7 '/api/user(.*)'
8])
9
10const isPublicRoute = createRouteMatcher([
11 '/',
12 '/sign-in(.*)',
13 '/sign-up(.*)',
14 '/api/webhooks(.*)'
15])
16
17export default clerkMiddleware(async (auth, req) => {
18 if (isProtectedRoute(req)) {
19 await auth.protect()
20 }
21})
22
23export const config = {
24 matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)']
25}Usage Examples#
Server Component#
1// app/dashboard/page.tsx
2import { auth } from '@clerk/nextjs/server'
3import { redirect } from 'next/navigation'
4
5export default async function DashboardPage() {
6 const { userId } = await auth()
7
8 if (!userId) {
9 redirect('/sign-in')
10 }
11
12 return <Dashboard userId={userId} />
13}Server Action#
1// actions/profile.ts
2'use server'
3
4import { auth } from '@clerk/nextjs/server'
5import { prisma } from '@/lib/db'
6
7export async function updateProfile(formData: FormData) {
8 const { userId } = await auth()
9
10 if (!userId) {
11 throw new Error('Unauthorized')
12 }
13
14 await prisma.user.update({
15 where: { clerkId: userId },
16 data: {
17 name: formData.get('name') as string
18 }
19 })
20}Best Practices#
- Always sync with database - Create a database user record to store app-specific data
- Use middleware for route protection - Centralize auth checks in middleware
- Handle loading states - Show loading UI while Clerk initializes on client
- Set up webhooks - Listen for user.created, user.updated, user.deleted events
- Use Server Components - Prefer server-side auth checks when possible
Related Patterns#
- Session Management - Managing user sessions
- RBAC - Role-based access control
- Prisma - Database integration