Next.js + Clerkで認証機能を作ってみた

Next.js

2024-09-16

はじめに

最近「Clerk」という認証ライブラリを知ったので、実際に触ってみた感想やNext.jsに組み込む方法をまとめる。

Clerkとは

ClerkNextAuth.js などと同じような認証ライブラリです。

メールアドレス・パスワード認証を始め、SNS認証、多要素認証(MFA)などの機能を数行のコードで実装でき、UIコンポーネントも用意してくれているので、簡単に認証機能を構築することが可能。

Next.js以外のRemixやAstro、React Nativeなどネイティブアプリに利用することができる。

Clerk側のセットアップ

Clerkを利用するにはアカウント登録が必要なので、まず登録を行う。

アカウント登録

Clerkアプリケーションの作成

続いて、Clerkアプリケーションを作成する。

フォームに入力した内容を元に、UIイメージを確認することができる。

入力させたい項目や、SNS認証として利用したいプロバイダーをここで選択する

画像の説明: create-clerk-app-3QhKwGNgtdXSKP0pqb0lN0eRyIE53p.png

これでClerk側のセットアップは完了!

Next.js側のセットアップ

Clerkのインストール

yarn add @clerk/nextjs

環境変数の設定

Clerkアプリケーション作成後に環境変数が発行されるので .env.local に記述する

画像の説明: config-env-ENRWYrVK3E28nE1Gx7sHm2gAccJHnA.png

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test...
CLERK_SECRET_KEY=sk_test...

ミドルウェアの作成

middleware.ts ファイルを作成し、下記のコード記述する

import { clerkMiddleware } from "@clerk/nextjs/server";

export default clerkMiddleware();

export const config = {
  matcher: [
    // Skip Next.js internals and all static files, unless found in search params
    "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
    // Always run for API routes
    "/(api|trpc)(.*)",
  ],
};

clerkMiddleware に保護したいルートを指定することで、認証済みでないとアクセスできないページを作れる

細かいルート設定は以下のURLを参照

https://clerk.com/docs/references/nextjs/clerk-middleware

ClerkProviderの設定

app/layout.tsxClerkProvider コンポーネントを追加して、どのページからでも認証済みのユーザー情報などの認証情報にアクセスできるようにする

import { ClerkProvider } from '@clerk/nextjs'
import './globals.css'
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body>
          {children}
        </body>
      </html>
    </ClerkProvider>
  )
}

サインイン・サインアップ画面の作成

サインアップ画面

app/sign-up/[[...sign-up]]/page.tsx のディレクトリ、ファイルを作成し、ClerkのSignUpコンポーネントを表示することで、アプリケーション作成時に設定した登録画面のUIを表示できる

import { SignUp } from "@clerk/nextjs";

const SignUpPage = () => {
  return (
    <div className="h-[calc(100vh-96px)] flex items-center justify-center">
      <SignUp />
    </div>
  );
}

export default SignUpPage;

画像の説明: create-account-component-jxLKOXmAByQCp4IvFnse5N5Pjjz4tc.png

サインイン画面

app/sign-in/[[...sign-in]]/page.tsx のディレクトリ、ファイルを作成し、ClerkのSignInコンポーネントを表示する

import { SignIn } from "@clerk/nextjs";

const SingInPage =() => {
  return (
    <div className="h-[calc(100vh-96px)] flex items-center justify-center">
      <SignIn />
    </div>
  );
}

export default SingInPage;

画像の説明: sign-in-component-OWMmDYRD2I8TJPhheY50QhtlZQCnmO.png

認証情報

サインインやサインアップを行うと、Clerkは認証ユーザの情報をJWTベースでセッション管理し、プラウザのCookieに付与する。

画像の説明: dev-tool-4j3vciX4NnFMZwFH2w5M90MLS8Cqma.png

認証中のユーザー情報はauth() ヘルパで取得できるため、認証ユーザーにのみページのUIを変更したい場合の判別データとして使える。

バックエンドリクエストの保護

バックエンドにNext.jsを利用している場合は、セットアップで作成したmiddleware.tsclerkMiddleware に保護したいAPIのパスを指定することで、バックエンドリクエストを保護できる。

バックエンドにNext.js以外を利用している場合は、Clerk SDKを利用する

下記の言語/フレームワークはSDKが提供されている。

提供されていない言語/フレームワークを使用している場合でもSDKを自作するためのドキュメントが用意されているため、作ることは可能

https://clerk.com/docs/references/sdk/overview

まとめ

自分は、フロントエンドの認証ライブラリを触ったことないためClerkを他のライブラリと比較することができないが、UIコンポーネントやダッシュボードが充実しているため、ユーザー情報の管理や認証フローの実装が簡単に行える点が良い。

また、設計が柔軟なため、フロントエンドからバックエンドまで幅広いカスタマイズに対応しているので採用しやすいライブラリだと思う。