A comprehensive guide to implementing authentication in your Next.js 14 application using Clerk.
This guide has been updated to use Clerk, a modern authentication solution for Next.js applications.
Clerk is a complete authentication and user management solution that provides a seamless way to add authentication to your Next.js applications. It offers features like:
First, install the Clerk Next.js package:
npm install @clerk/nextjs
# or
yarn add @clerk/nextjs
# or
pnpm add @clerk/nextjs
Create or update your
.env.localNEXT_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
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard
next.config.jsUpdate your Next.js configuration to include Clerk's domains:
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
domains: ['images.unsplash.com', 'img.clerk.com'],
},
};
module.exports = nextConfig;
Update your root layout to include the
ClerkProvider// app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<ClerkProvider>
<body>{children}</body>
</ClerkProvider>
</html>
);
}
Create a middleware file to protect your routes:
// middleware.ts
import { authMiddleware } from '@clerk/nextjs';
export default authMiddleware({
// Public routes that don't require authentication
publicRoutes: ['/', '/sign-in(.*)', '/sign-up(.*)'],
});
export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};
Create a sign-in page:
// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs';
export default function SignInPage() {
return (
<div className="flex min-h-screen items-center justify-center">
<SignIn path="/sign-in" routing="path" signUpUrl="/sign-up" />
</div>
);
}
Create a sign-up page:
// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs';
export default function SignUpPage() {
return (
<div className="flex min-h-screen items-center justify-center">
<SignUp path="/sign-up" routing="path" signInUrl="/sign-in" />
</div>
);
}
Use
auth()// app/dashboard/page.tsx
import { auth } from '@clerk/nextjs';
export default async function DashboardPage() {
const { userId } = auth();
if (!userId) {
return <div>Not authenticated</div>;
}
return (
<div>
<h1>Welcome to your dashboard!</h1>
<p>User ID: {userId}</p>
</div>
);
}
Use
useUser()// components/UserButton.tsx
'use client';
import { UserButton } from '@clerk/nextjs';
export default function UserProfile() {
return (
<div>
<UserButton afterSignOutUrl="/" />
</div>
);
}
Create a custom user profile page:
// app/profile/page.tsx
import { auth } from '@clerk/nextjs';
export default async function ProfilePage() {
const { userId } = auth();
if (!userId) {
return <div>Please sign in to view your profile</div>;
}
return (
<div className="max-w-2xl mx-auto p-6">
<h1 className="text-2xl font-bold mb-6">Your Profile</h1>
<div className="space-y-4">
<div>
<h2 className="font-semibold">User ID</h2>
<p className="text-gray-600">{userId}</p>
</div>
</div>
</div>
);
}
Protect your API routes:
// app/api/protected/route.ts
import { auth } from '@clerk/nextjs';
import { NextResponse } from 'next/server';
export async function GET() {
const { userId } = auth();
if (!userId) {
return new NextResponse('Unauthorized', { status: 401 });
}
return NextResponse.json({ data: 'Protected data' });
}
Clerk provides a powerful and flexible authentication solution for Next.js applications. With its pre-built components and easy-to-use API, you can quickly add secure authentication to your application.
For more information, check out the Clerk documentation.
Clerk not loading
.env.localMiddleware issues
API route protection
auth()If you run into any issues, check out the Clerk documentation or join the Clerk community for support.