🔧 Implementing Authentication with Clerk in Next.js
Nachrichtenbereich: 🔧 Programmierung
🔗 Quelle: dev.to
Introduction
Hello! I'm Atsushi, a cloud engineer working at a SaaS company in Tokyo. Recently, I implemented authentication features for my personal AI chatbot project using Clerk, an authentication service. I'd like to share the insights I gained from this experience.
What is Clerk?
Clerk is a service that provides embeddable UI components, APIs, and an administrative dashboard for user authentication and management. It supports frontend frameworks like Next.js, React, and Remix.
In addition to authentication features, Clerk offers UI components that make it easy to implement sign-in and login screens. It also integrates with services like Supabase and Firebase.
Account Creation
To get started with Clerk:
- Sign up at Clerk's website by clicking the "Get started" button.
- After creating an account, set up your application by providing a name and clicking "Create application".
Implementing Authentication Screens
Clerk provides UI components that make it easy to implement authentication screens. This guide focuses on implementation with Next.js using the App Router.
Prerequisites
- Set environment variables in
.env.local
:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=xxx
CLERK_SECRET_KEY=xxx
- Set up the Clerk Provider in
app/layout.tsx
:
import { ClerkProvider } from '@clerk/nextjs'
import { jaJP } from '@clerk/localizations'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<ClerkProvider localization={jaJP}>
<html>
<body>
<main>{children}</main>
</body>
</html>
</ClerkProvider>
)
}
- Implement Middleware in
middleware.ts
:
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
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)(.*)',
],
}
Using Standard Components
Clerk provides ready-to-use components like <SignUp />
and <SignIn />
that can be easily implemented:
import { SignUp } from '@clerk/nextjs'
export default function Page() {
return <SignUp />
}
Custom Implementation with React Hook Form
For more control over the form, you can use React Hook Form with Clerk's helpers:
- Create a custom hook (
useSignInForm
):
import { useSignIn } from '@clerk/nextjs'
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
// ... (schema and type definitions)
export const useSignInForm = () => {
const { isLoaded, setActive, signIn } = useSignIn()
// ... (form setup and submit handler)
}
- Create a Form Provider:
import { useSignInForm } from '@/hooks/sign-in/use-sign-in'
import { FormProvider } from 'react-hook-form'
const SignInFormProvider = ({ children }: Props) => {
const { methods, onHandleSubmit, loading } = useSignInForm()
return (
<FormProvider {...methods}>
<form onSubmit={onHandleSubmit}>{children}</form>
</FormProvider>
)
}
- Create the Form component:
import { useFormContext } from 'react-hook-form'
const LoginForm = () => {
const {
register,
formState: { errors },
} = useFormContext()
return (
<>
<h2>Login</h2>
<input {...register('email')} />
<input {...register('password')} />
</>
)
}
- Implement the login page:
import SignInFormProvider from '@/components/forms/sign-in/form-provider'
import LoginForm from '@/components/forms/sign-in/login-form'
const SignInPage = () => {
return (
<SignInFormProvider>
<LoginForm />
<button type="submit">Login</button>
</SignInFormProvider>
)
}
Retrieving Authentication Information
To get the user ID after sign-up:
import { currentUser } from '@clerk/nextjs/server'
const user = await currentUser()
const id = user.id
Conclusion
Clerk significantly simplifies the implementation of authentication features.
Its flexibility allows for easy integration with popular tools like React Hook Form and Zod.
However, for Next.js projects, alternatives like Auth.js or Supabase's built-in authentication should also be considered depending on the use case.