🔒

Clerkで爆速認証実装 - Next.jsアプリに10分で認証機能を追加する

に公開

皆さんは「認証機能の実装に何日もかけているうちに、本来作りたかった機能の開発が進まない」「自分で書いた認証コードが本当にセキュアなのか不安になる」といったことで悩んでいませんか?

そこで、Clerkというオススメの認証サービスを紹介します。Clerkでは、構築済みのコンポーネントと認証ロジックを使用して、非常に少ないコード量で認証ページを作成することができます。それだけでなく、Clerk Dashboardを使用したGUIベースの高度な設定も可能です。
認証プロバイダーとしてIDとパスワードでの認証はもちろん、OAuth2や電話番号、パスキーでの認証にも対応しています。認証/認可のみならず、攻撃からの保護や構築済みUIの見た目のカスタマイズ、組織の管理、最近ではStripeと連携した請求までをこのサービスのみで実装できます。

このように、Clerkでは認証/認可の開発効率と安全性を大幅に向上させるだけでなく、アプリケーションを構築する上で重要な機能を幅広く有しています。
そこで、Clerkへの入り口・入門編としてNext.js、Hono、Clerkを活用し、フロントエンドからバックエンドまで一気通貫で認証の実装方法とその知見を、全3回に分けて共有します。


本記事では、Next.jsとClerkを使用したフロントエンド認証を取り扱います。

  1. Clerkで爆速認証実装 - Next.jsアプリに10分で認証機能を追加する(今ここ)
  2. Clerk × Hono で実現するシンプルで安全なバックエンド認証
  3. WebhookによるClerkとアプリケーションデータの同期

対象読者

  • Next.jsでのアプリケーション開発経験がある方
  • 認証機能の実装に時間を取られたくない方
  • セキュリティを考慮した認証を手軽に導入したい方
  • Clerkの導入を検討している方

実行環境

  • OS: Ubuntu 22.04.5 LTS(WSL2)
  • Node.js: v22.16.0
  • pnpm: 10.12.2
  • Next.js: 15.3.5
  • React: ^19.0.0
  • @clerk/nextjs: ^6.27.1

Clerkとは

Clerkは、モダンなWebアプリケーション向けの認証・ユーザー管理プラットフォームです。従来の認証実装で必要だった複雑な設定やセキュリティ対策を、開発者フレンドリーなAPIとUIコンポーネントで解決します。

Clerkの主な特徴

  • 手軽さと柔軟さを兼ね備えたSDK: Clerkは構築済みのUIコンポーネントを提供しており、たった数行のコードで見た目が整ったサインインページなどを作成することができます。それだけでなく、カスタムフックなどを利用することで、アプリケーションのブランドに即したカスタムのページを作成することができます。
  • 豊富なドキュメント: 公式ドキュメントが豊富で非常にわかりやすく書かれています。執筆時点(2025年6月)では、ZennでClerkトピックがついた記事は140記事ほどですが、公式ガイドを機械翻訳で読むだけでも十分にアプリケーションを構築できます。
  • 多様な認証方法: Email、ユーザーネームはもちろん、24以上のOAuth2プロバイダー、カスタムプロバイダーにも対応しています。パスキーにも対応しており、かなりモダンで幅広い認証方法を提供していることがわかります。

Next.jsプロジェクトのセットアップ

今回はopennextを使用したNext.jsアプリケーションを作成します。第2、3回でCloudflareへのデプロイを行うため、簡単にCloudflareにデプロイできるopennextを使用しています。
以下のコマンドを使用し、プロジェクトを初期化します。

pnpm create cloudflare@latest -- --framework=next --platform=workers

In which directory do you want to create your application?では、./.を入力。

What would you like to start with?では、FrameWork Starterを選択

Which development framework do you want to use?では、Next.jsを選択
以降の質問では、Would you like to customize the import alias (@/* by default)?以外をすべてYesにします。
↓実行例

Create an application with Cloudflare Step 1 of 3

In which directory do you want to create your application?
dir ./.

What would you like to start with?
category Framework Starter

Which development framework do you want to use?
framework Next.js

Select your deployment platform
platform Workers with Assets

✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like your code inside a `src/` directory? … Yes
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to use Turbopack for `next dev`? … Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No

Clerkのセットアップ

ここからClerkのプロジェクトを作成することができます。
Clerkでは多数の認証方法を提供しており、選択に応じて自動的にサインインコンポーネントを生成します。このUIコンポーネントをインポートするだけで、即座にサインインフローが完成することが強みです。

今回はフローの簡略化のためEmailとUsernameによる認証のみにしますが、OAuth2認証にも対応しているため、プロジェクトの要件によって適宜変更してください。
Clerkダッシュボード

Create applicationをクリックすると、プロジェクトが作成され、ダッシュボードに遷移します。
ダッシュボードには各フレームワークへの導入方法が丁寧に記載されているので、これに従うだけで導入が完了します。今回はNext.jsを使用するため、一番左のタブの指示に従います。
Clerkドキュメント

アプリケーションへの導入

次に、Clerkを使用してアプリケーションへ認証をかけるための手順を紹介します。
Clerkの公式SDKを使用することで、サインインページや認証ルールを簡単に実装できます。

まずは任意のパッケージマネージャを使用して、ClerkのNext.js SDKをインストールします。

pnpm add @clerk/nextjs

その後、ルートディレクトリに.envファイルを作成し、ClerkのAPIキーを設定します。

.env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxxxxxxx...
CLERK_SECRET_KEY=sk_test_xxxxxxxxxx...

Next.jsミドルウェアの作成

Clerkでは、Next.jsのミドルウェアを使用して認証状態のチェックやパスの振り分けを行います。
SDKを使用することで、わずか数行のコードで安全な認証機能を実装できます。

今回使用する主要な関数は以下の通りです:

  • clerkMiddleware: Clerk認証をNext.jsに統合
  • createRouteMatcher: 認証ルールを定義
  • auth.protect(): 認証状態をチェック

createRouteMatcherで認証不要なパス(パブリックルート)を定義し、それ以外のパスで認証チェックを実行します。今回は/sign-inのみをパブリックルートに設定しています。

src/middleware.tsを作成し、そこにClerkで認証するためのコードを記述します。

src/middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

// パブリックルートの定義
const isPublicRoute = createRouteMatcher(['/sign-in(.*)'])

export default clerkMiddleware(async (auth, req) => {
  // パブリックルート以外の場合、認証チェックを実行
  if (!isPublicRoute(req)) await auth.protect()
})

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)(.*)',
  ],
}

ClerkProviderの設定

ここまで、SDKとミドルウェアでアクセス制御の仕組みを整えてきましたが、このままではClerkのUIコンポーネント(サインインボタンやユーザープロフィールなど)を使うことができません。これらのコンポーネントを使うためには、ClerkProviderでアプリケーションを囲む必要があります。
layout.tsxを使用して、アプリケーションのトップレベルでClerkProviderを使用して全体を囲みます。

src/app/layout.tsx
import type { Metadata } from 'next'
import {
  ClerkProvider,
} from '@clerk/nextjs'
import { Geist, Geist_Mono } from 'next/font/google'
import './globals.css'

const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
})

const geistMono = Geist_Mono({
  variable: '--font-geist-mono',
  subsets: ['latin'],
})

export const metadata: Metadata = {
  title: 'Clerk Next.js Quickstart',
  description: 'Generated by create next app',
}

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode
}>) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
          {children}
        </body>
      </html>
    </ClerkProvider>
  )
}

サインインページの作成

アプリケーション全体でClerkを使用する準備が整ったため、サインインページを作成します。
Clerkは構築済みのUIを提供しているため、Clerkの初期設定時に右側に表示されていたコンポーネントをインポートするだけで簡単にサインインページを構築できます。

src/app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from "@clerk/nextjs";

export default function SignInPage() {

    return (
        <div className="w-dvw h-dvh flex justify-center items-center">
            <SignIn/>
        </div>
    )
}

パスの指定

Clerkでは環境変数を使用してサインインページやサインイン後のリダイレクト先のパスを指定するため、.envファイルに以下を書き込みます。

.env
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in          # サインインページのパス
NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL=/  # サインイン後のリダイレクト先

共通ヘッダーの作成

Clerkでは、SignInのようなコンポーネントのほかに、制御コンポーネントを使用することができます。このコンポーネントでは、サインイン状態でのみ子コンポーネントを表示するなど、直接的には見た目を提供しないものの、アプリケーションの見た目を制御するのに使用できるコンポーネントも提供しています。

ここでは、Clerkが提供する以下のコンポーネントを使用しています:

  • SignedOut: サインアウト状態でのみ表示される
  • SignedIn: サインイン状態でのみ表示される
  • SignInButton: サインインボタン
  • SignUpButton: サインアップボタン
  • UserButton: サインイン済みユーザーのプロフィールボタン

SignedInコンポーネントを使用して、サインイン時にはユーザープロフィールを、SignedOutコンポーネントを使用してサインアウト時にはサインイン/サインアップボタンを表示するようにしています。

src/app/layout.tsx
<html lang="en">
  <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
    <header className="flex justify-end items-center p-4 gap-4 h-16">
      <SignedOut>
        <SignInButton />
        <SignUpButton />
      </SignedOut>
      <SignedIn>
        <UserButton />
      </SignedIn>
    </header>
    {children}
  </body>
</html>

アプリケーションの確認

開発サーバーを起動してアプリケーションを確認します。

pnpm dev

http://localhost:3000にアクセスすると、自動的に/sign-inページにリダイレクトされます。これは、ミドルウェアで/sign-in以外のページに認証制限をかけているためです。

サインインページ

サインアップを完了すると、トップページ(/)にアクセスできるようになり、ヘッダーにUserButtonが表示されます。これをクリックすることで、アカウントの管理やサインアウトができるようになります。

ユーザーボタン

まとめ

本記事では、ClerkとNext.jsを使用して認証機能を実装する方法を紹介しました。従来の認証実装では複雑な設定やセキュリティ対策が必要でしたが、Clerkを使用することで、わずか数十行のコードで安全かつ機能的な認証システムを構築できることがわかりました。特に、構築済みのUIコンポーネントと直感的なAPIにより、開発時間を大幅に短縮できる点が大きなメリットです。

次回の記事では、HonoとClerkを組み合わせたバックエンドAPI認証の実装について解説し、フロントエンドとバックエンドを連携させた本格的な認証システムの構築方法をお伝えします。

株式会社SCC - テクノロジーセンター

Discussion