Published on October 22, 2025
Almost all developers should be using an authentication service, as DIY security is notoriously hard to get right. Auth providers like Firebase and AWS Cognito have been around for some time, but they can be frustrating to use, requiring you to sift through fragmented documentation and implement custom logic and UI.
Clerk auth offers a better approach with prebuilt authentication components, modern flexible SDKs, and sensible defaults that help you get up and running fast, especially if you're working with JavaScript.
Here, we give a rundown of Clerk and its benefits, and we show you how to implement it in a Next.js app.
Clerk auth, or simply Clerk, is a full authentication and user management service for web and mobile apps. It handles authentication for you, including MFA, OAuth, sessions, tokens, and social login. Clerk simplifies authentication by providing prebuilt UI components for sign-in, signup, user profiles, and session management while still being flexible with customization. You can configure aspects of your authentication setup through the web dashboard, choosing which sign-in methods to enable and whether to allow MFA.
Clerk is a paid service but has a free tier for up to 10,000 monthly active users, charging $25 per month from there on. It also has multi-tenancy Clerk B2B, which can support organizations with multiple users. This is especially useful to SaaS companies where each customer can be a company rather than an individual user.
Although Clerk provides SDKs for many different languages, it's designed to work best with JavaScript frameworks like React and Vue. It's especially straightforward to implement Clerk authentication flows in Next.js, with which it has a deep integration.
This is a high-level flow of how Clerk auth validates a user session in a Next.js application. Requests pass through Clerk for JWT validation, it redirects unauthenticated users to sign in and authenticated users to the requested protected page.
If you want to add authentication to your app quickly, Clerk presents itself as a good choice. It's common to start off with a temporary auth solution (using Github OAuth, for example), which works well at first, but as your product starts to scale, you may need to add roles, permissions, and multi-provider support. At this point, you want to integrate something quickly that works well with some level of customization.
With Clerk, you can get something up and running in minutes by starting with their fastest option: using their hosted sign-in and signup pages. Alternatively, you can use their existing prebuilt UI components and authentication flows, using default values at first and customizing them later once everything is working smoothly.
Clerk also presents itself as a great choice for small startup teams. It saves time by avoiding the need to build custom authentication flows, as well as making sure the solution aligns with the latest security standards and compliance requirements. It’s also a good choice for most B2B SaaS apps, with built-in support for multi-tenancy, roles, fine-grained permissions, and SAML support.
Clerk isn’t the only option in this space. To put it in context, here’s a quick comparison with Auth0 and Auth.js:
Feature / Service | Clerk | Auth0 | Auth.js (open source) |
---|---|---|---|
Ease of setup | Drop-in UI components, hosted flows, fast Next.js integration | Powerful but more complex setup | DIY, requires more manual wiring |
Framework support | First-class for Next.js, React, Vue | Broad support | Works across frameworks but minimal UI |
Enterprise features | Orgs, roles, multi-tenancy, SAML | Strong enterprise suite | None out of the box |
Pricing | Free tier (10k MAU), scales with usage | Usage-based, higher at scale | Free, but dev time is the “cost” |
Clerk provides a lot of benefits preconfigured and ready to use, so it takes little effort to get your authentication solution integrated:
There are three main ways to implement auth with Clerk:
Hosted solution (fastest to ship): Clerk hosts pre-built pages for signup, sign-in, and account management on Clerk-managed subdomains. You don't need to develop these pages yourself; you only need to implement buttons that integrate with them. When a logged-out user clicks a button to log in, they get redirected to the Clerk-hosted sign-in page. Clerk then manages the entire authentication flow before returning the logged-in user back to your app.
Prebuilt Clerk UI components: Clerk provides ready-made UI components for frameworks like React and Vue (for example, <SignIn />
, <SignUp />
, and <UserButton />
) that you can import and drop into your code. This provides a better user experience than the hosted solution, as the user remains inside your app instead of being redirected somewhere external. In this case, when a logged-out user clicks a button to log in, the <SignIn>
component handles the authentication flow by calling Clerk's SDK. These UI components are customizable to allow for flexibility, so this is the most common way to use Clerk.
Completely custom UI: You build the entire UI just using Clerk's hooks (useAuth()
, useUser()
) and API calls. Most of the time you won't need to do this, since the prebuilt UI components are already customizable, but the option is there to replace any component with your own if you need a non-standard auth flow or a highly bespoke layout that fits 100% with your branding.
Depending on whether the user successfully logged in or not, they’ll be redirected to a different page. Clerk has defaults for these pages, but you can override them in the Clerk dashboard by changing the values of redirectUrl
and afterSignInUrl
.
You can add multifactor authentication (MFA) by turning it on from the Clerk dashboard. The MFA step will then be automatically added to your hosted signup/sign-in page or prebuilt UI components. You can choose to enable MFA app-wide, per organization, or as an extra step for sensitive operations.
It's also relatively straightforward to add social SSO; you just have to enable providers (like Google, GitHub) in the Clerk dashboard, and they’ll appear automatically in your hosted pages or <SignIn/>
component.
Clerk provides a few tools to help you protect and control access to your routes. You can wrap your application’s middleware with clerkMiddleware
to handle authentication/authorization and any redirects for unauthenticated users. You can also protect individual routes by requiring users to sign in with auth.protect()
. The function createRouteMatcher()
allows you to define groups of routes with patterns and then apply protection to them all at once, avoiding repetition in your code.
Clerk provides organizations, a feature that groups a bunch of user accounts together that all work for the same company or team. This is especially useful for B2B SaaS apps that need to support multi-tenancy for their different clients.
It also supports user roles that you can use to define permissions and different access levels within your app.
Clerk supports SAML and has implemented SAML flows for you, so there's no need to build or maintain custom SAML flows for your enterprise customers.
Clerk lets you add custom fields during data registration and persist them as part of the user object using metadata (public, private, or unsafe). This makes it possible to capture extra details like “company name” or “team size” when a user signs up. All captured registration data is visible in Clerk’s admin dashboard and accessible programmatically via the API. This makes it straightforward to provide user support and manage accounts.
Security should be a priority at any company, and Clerk has you covered. It comes with enterprise-grade security features already built in. It’s SOC 2 Type II compliant, and is regularly audited to ensure security controls meet industry standards, so customer data stays safe. It also provides automated protections to stop malicious activities like credential stuffing and repeated login attempts before they reach your app. In addition, Clerk checks user passwords against known breach databases, and you can configure it to force resets if credentials have been compromised.
Clerk puts a lot of emphasis on making the developer experience as smooth as possible, so you can spend less time tinkering with auth and more time building the features that make your app stand out. It provides clear documentation and APIs, making implementation and integration straightforward. Clerk provides a dedicated support team and an active community to help unblock you if you get stuck.
Clerk can also work with CLIs. You can set up long-lived tokens with JWT templates to authenticate command line access to your application’s APIs. It also has a migration script that helps you to migrate existing users if you're moving from another auth system.
The following tutorial will show you how to build a small Next.js app with a home page and a protected page (in this case a user dashboard) that uses Clerk for authentication. You can download the repo for this tutorial or follow along.
First you need to sign up to Clerk, create a new application, navigate to API keys under Configure, and copy the public and secret keys to save somewhere for later.
Bootstrap a new Next.js project by running the following command in your terminal:
npx create-next-app@latest clerk-next-app --typescript
When setting up your Next.js project in the CLI, make sure to have your code in a src
directory and use the App Router.
Once ready, change directory into your Next.js project and install the Clerk SDK:
Create a .env.local
file in the root of your project and paste in the keys you copied from Clerk earlier.
In the src/app/layout.tsx
file, wrap the app with the <ClerkProvider>
component. This makes Clerk's authentication functions available throughout your app:
Create a middleware.ts
file in the src
directory of your project and add clerkMiddleware
to protect your routes:
The code above checks whether the route is protected and if the user is authenticated; if not, then it redirects back to the home page.
Create a dashboard component in /src/app/dashboard/page.tsx
:
The code above uses Clerk's <UserButton/>
, which is a prebuilt account menu widget that provides account management options for the current user, as well as the ability to sign out. The dashboard component also displays the user's first name if it exists in the user
object.
Now in the app directory, replace the code in page.tsx
with the following to add a sign-in button to the home page:
A logged-out user will see the <SignInButton>
component, which is just a button that opens a Clerk-hosted <SignIn>
component. This gives you options to sign up or sign in with your email account or any other social account that you enabled when setting up your Clerk account.
This code also uses <SignedOut>
and <SignedIn>
to display different information based on whether the user is logged in or not.
To test your code, start up your app with:
and go to http://localhost:3000/dashboard
in your browser. You should now see that the dashboard is protected. When you are not logged in, it’ll just redirect you back to the homepage.
Go to the homepage at http://localhost:3000/
and click the Sign in button. Follow the instructions to sign in, including signing up if you need to. Once logged in, you should be redirected automatically to the dashboard. Now that you're logged in, you should see a welcome message and your first name:
If you experience any CORS (Cross-Origin Resource Sharing) issues when logging in, it's worth running this in an incognito tab.
Clerk sets a session cookie on your domain after sign-in. Then, in your server code, the Clerk-provided helpers auth()
and currentUser()
read that session to identify the user. If your app needs to call other back ends that require user authentication, you can create a JWT template in your Clerk dashboard and then call getToken({template})
in your code to obtain a signed JWT for downstream verification.
There are some pitfalls to look out for when using Clerk:
Middleware conflicts: Use only one middleware.ts
file at your project root. It can be tempting to have separate middleware for different areas like /dashboard
and /api
, but this can lead to conflicts or redirect loops. Wrap your entire handler in clerkMiddleware
and use a broad matcher
to apply your middleware so that when you add more routes to your app later, they don't get missed.
Double redirects: Don’t manually redirect on /dashboard
(for example, sending unauthenticated users to /sign-in
). Although this might feel natural if you’ve implemented auth manually before, the middleware file is where you should handle this authentication logic. If you don’t centralize this check, you risk double redirects.
Mixing client and server auth in App Router: Next.js AppRouter has two similar-sounding imports: @clerk/nextjs
is a client-side helper and @clerk/nextjs/server
is a server-side helper. The wrong import will break your code.
Clerk ties together everything you need for a modern authentication solution with a simple setup, pre-built UI, and enterprise features like roles and SAML. Instead of writing custom auth logic yourself, you get a product that’s straightforward to implement that scales well. To see how Clerk fits into a broader stack, let’s add a content layer with Contentful.
As an example use case, imagine using Contentful to serve your Next.js app's blog posts. You could use the Contentful Content Platform to mark some blog posts with an isPremium
field.
Then with Clerk auth, you could manage which users have premium access by assigning them a role or subscription plan. When a user lands on a premium post, Clerk could check their session and permissions. Non-members would see a teaser, while logged-in premium users would get the full article.
This approach would allow you to combine Contentful's content modeling and personalization features with Clerk's authentication and authorization, giving you a way to protect premium experiences and deliver content efficiently.
It also provides a way to make good use of Contentful's fast, optimized content delivery: because Contentful uses a GraphQL API to serve content from a high-speed global CDN, your app fetches only the fields it needs for each type of user. Non-premium users might only need to see the title and excerpt, while premium users might need the full body text. Loading only the content that's needed allows your app to have lightning-fast performance.
Inspiration for your inbox
Subscribe and stay up-to-date on best practices for delivering modern digital experiences.