mcpField
C
clerk-auth

clerk-auth

github.com/jackspaceセキュリティ1637 回インストール12 週間前に更新
リポジトリ

clerk-auth について

clerk-auth は、Clerk 認証の実装ガイドです。React、Next.js、Cloudflare Workers を使う開発者向けに、アプリ設定、ルート保護、トークン検証、カスタム JWT クレーム、テストを扱います。

主な機能

  1. 01React と Next.js の認証設定
  2. 02アプリのルート保護
  3. 03Cloudflare Workers でのトークン検証
  4. 04カスタム JWT クレームの作成
  5. 05提供された認証情報でのテスト

活用シーン

  1. 01React や Next.js アプリへのサインイン追加
  2. 02未認証リクエストからのルート保護
  3. 03Cloudflare Workers でのセッショントークン確認
  4. 04マルチテナントアプリ向け JWT クレーム設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jackspace/claudeskillz --skill clerk-auth

インストール後、Claude Code で/clerk-authを入力して読み込まれたか確認します。

同梱ファイルREADME.mdSKILL.json

詳細

Clerk 認証

ステータス:本番環境で使用可能 ✅ 最終更新日:2025-10-28 依存関係:なし 最新バージョン:@clerk/[email protected]、@clerk/[email protected]、@clerk/[email protected]、@clerk/[email protected]


クイックスタート(10 分)

フレームワークを選択してください:


React(Vite)のセットアップ

1. Clerk をインストールする

```bash npm install @clerk/clerk-react ```

最新バージョン:@clerk/[email protected](2025-10-22 に確認済み)

2. ClerkProvider を設定する

`src/main.tsx` を更新します:

```typescript import React from 'react' import ReactDOM from 'react-dom/client' import { ClerkProvider } from '@clerk/clerk-react' import App from './App.tsx' import './index.css'

// 環境変数から公開可能キーを取得 const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY

if (!PUBLISHABLE_KEY) { throw new Error('Missing Publishable Key') }

ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> </React.StrictMode>, ) ```

重要:

3. 環境変数を追加する

`.env.local` を作成します:

```bash VITE_CLERK_PUBLISHABLE_KEY=pk_test_... ```

セキュリティに関する注意:`VITE_` プレフィックス付きの変数のみがクライアントコードに公開されます。

4. 認証フックを使用する

```typescript import { useUser, useAuth, useClerk } from '@clerk/clerk-react'

function App() { // ユーザーオブジェクトを取得(メールアドレス、メタデータなどを含む) const { isLoaded, isSignedIn, user } = useUser()

// 認証状態とセッションのメソッドを取得 const { userId, sessionId, getToken } = useAuth()

// 高度な操作用に Clerk インスタンスを取得 const { openSignIn, signOut } = useClerk()

// 認証に依存する UI をレンダリングする前に、必ず isLoaded を確認する if (!isLoaded) { return

Loading...
}

if (!isSignedIn) { return <button onClick={() => openSignIn()}>Sign In }

return (

ようこそ、{user.firstName}さん!

メールアドレス:{user.primaryEmailAddress?.emailAddress}

<button onClick={() => signOut()}>サインアウト
) } ```

これが重要な理由:

  • `isLoaded` により、誤ったコンテンツが一瞬表示されるのを防げます
  • `useUser()` はメタデータを含む完全なユーザーオブジェクトを提供します
  • `useAuth()` はセッショントークンと認証状態を提供します
  • ソース:https://clerk.com/docs/references/react/use-user

Next.js App Router のセットアップ

1. Clerk をインストールする

```bash npm install @clerk/nextjs ```

最新バージョン:@clerk/[email protected](2025-10-22 に確認済み)

2. 環境変数を設定する

`.env.local` を作成します:

```bash NEXT_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=/onboarding ```

重要:

3. ルート保護用のミドルウェアを追加する

プロジェクトのルートに `middleware.ts` を作成します。

```typescript import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

// 公開するルートを定義します(それ以外のすべてのルートでは認証が必要です) const isPublicRoute = createRouteMatcher([ '/', '/sign-in(.)', '/sign-up(.)', '/api/webhooks(.*)', // Clerk の Webhook は公開する必要があります ])

export default clerkMiddleware(async (auth, request) => { // 公開ルート以外のすべてのルートを保護します if (!isPublicRoute(request)) { await auth.protect() } })

export const config = { matcher: [ // Next.js の内部ルートと静的ファイルを除外します '/((?!_next|[^?]\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).)', // API ルートでは常に実行します '/(api|trpc)(.*)', ], } ```

重要:

  • v6 では `auth.protect()` は非同期です(v5 からの破壊的変更)
  • `createRouteMatcher()` はグロブパターンを受け付けます
  • 別の方法として、ロジックを反転させずに特定のルートを保護できます
  • 出典:https://clerk.com/docs/reference/nextjs/clerk-middleware
4. アプリを ClerkProvider でラップする

`app/layout.tsx` を更新します。

```typescript import { ClerkProvider } from '@clerk/nextjs' import './globals.css'

export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } ```

5. サーバーコンポーネントで auth() を使用する

```typescript import { auth, currentUser } from '@clerk/nextjs/server'

export default async function DashboardPage() { // 認証状態を取得します(軽量) const { userId, sessionId } = await auth()

// ユーザーオブジェクト全体を取得します(より負荷が高く、呼び出し回数は少なくなります) const user = await currentUser()

if (!userId) { return

認証されていません
}

return (

ダッシュボード

ユーザー ID:{userId}

メールアドレス:{user?.primaryEmailAddress?.emailAddress}

) } ```

重要:

  • v6 では `auth()` は非同期です(破壊的変更)
  • 軽量なチェックには `auth()` を使用します
  • ユーザーオブジェクト全体が必要な場合は `currentUser()` を使用します

Cloudflare Workers のセットアップ

1. 依存関係をインストールする

```bash npm install @clerk/backend hono ```

最新バージョン:

2. 環境変数を設定する

ローカル開発用に `.dev.vars` を作成します。

```bash CLERK_SECRET_KEY=sk_test_... CLERK_PUBLISHABLE_KEY=pk_test_... ```

本番環境:`wrangler secret put CLERK_SECRET_KEY` を使用します

3. トークン検証を実装する

src/index.ts を作成します。

import { Hono } from 'hono'
import { verifyToken } from '@clerk/backend'

type Bindings = {
  CLERK_SECRET_KEY: string
  CLERK_PUBLISHABLE_KEY: string
}

type Variables = {
  userId: string | null
  sessionClaims: any | null
}

const app = new Hono<{ Bindings: Bindings; Variables: Variables }>()

// ミドルウェア:Clerk トークンを検証
app.use('/api/*', async (c, next) => {
  const authHeader = c.req.header('Authorization')

  if (!authHeader) {
    c.set('userId', null)
    c.set('sessionClaims', null)
    return next()
  }

  const token = authHeader.replace('Bearer ', '')

  try {
    const { data, error } = await verifyToken(token, {
      secretKey: c.env.CLERK_SECRET_KEY,
      // 重要:CSRF 攻撃を防ぐため、authorizedParties を設定してください
      authorizedParties: ['https://yourdomain.com'],
    })

    if (error) {
      console.error('Token verification failed:', error)
      c.set('userId', null)
      c.set('sessionClaims', null)
    } else {
      c.set('userId', data.sub)
      c.set('sessionClaims', data)
    }
  } catch (err) {
    console.error('Token verification error:', err)
    c.set('userId', null)
    c.set('sessionClaims', null)
  }

  return next()
})

// 保護されたルート
app.get('/api/protected', (c) => {
  const userId = c.get('userId')

  if (!userId) {
    return c.json({ error: 'Unauthorized' }, 401)
  }

  return c.json({
    message: 'This is protected',
    userId,
    sessionClaims: c.get('sessionClaims'),
  })
})

export default app

重要:


JWT テンプレートとカスタムクレーム

Clerk では、テンプレートを使って JWT(JSON Web Token)の構造をカスタマイズできます。これにより、サードパーティサービスとの連携、ロールベースのアクセス制御、マルチテナントアプリケーションが可能になります。

クイックスタート:JWT テンプレートを作成する

1. Clerk Dashboard に移動します:

  • Sessions ページに移動します
  • Customize session token をクリックします
  • Create template をクリックします

2. テンプレートを定義します:

{
  "user_id": "{{user.id}}",
  "email": "{{user.primary_email_address}}",
  "role": "{{user.public_metadata.role || 'user'}}"
}

3. コードでテンプレートを使用します:

// Frontend (React/Next.js)
const { getToken } = useAuth()
const token = await getToken({ template: 'my-template' })

// Backend (Cloudflare Workers)
const sessionClaims = c.get('sessionClaims')
const role = sessionClaims?.role
使用可能なショートコード
カテゴリショートコード例
ユーザー ID と名前{{user.id}}、{{user.first_name}}、{{user.last_name}}、{{user.full_name}}"John Doe"
連絡先{{user.primary_email_address}}、{{user.primary_phone_address}}"[email protected]"
プロフィール{{user.image_url}}、{{user.username}}、{{user.created_at}}"https://..."
検証{{user.email_verified}}、{{user.phone_number_verified}}true
メタデータ{{user.public_metadata}}、{{user.public_metadata.FIELD}}{"role": "admin"}
組織org_id、org_slug、org_role(sessionClaims 内)"org:admin"
高度な機能

文字列補間:

{
  "full_name": "{{user.last_name}} {{user.first_name}}",
  "greeting": "Hello, {{user.first_name}}!"
}

条件付きフォールバック:

{
  "role": "{{user.public_metadata.role || 'user'}}",
  "age": "{{user.public_metadata.age || 18}}",
  "verified": "{{user.email_verified || user.phone_number_verified}}"
}

ドット記法によるネストされたメタデータ:

{
  "interests": "{{user.public_metadata.profile.interests}}",
  "department": "{{user.public_metadata.department}}"
}
デフォルトクレーム(自動的に含まれます)

すべての JWT には、次のクレームが自動的に含まれます(上書きできません)。

{
  "azp": "http://localhost:3000",              // Authorized party
  "exp": 1639398300,                            // Expiration time
  "iat": 1639398272,                            // Issued at
  "iss": "https://your-app.clerk.accounts.dev", // Issuer
  "jti": "10db7f531a90cb2faea4",               // JWT ID
  "nbf": 1639398220,                            // Not before
  "sub": "user_1deJLArSTiWiF1YdsEWysnhJLLY"    // User ID
}
サイズ制限:カスタムクレームは 1.2KB

問題:ブラウザーの Cookie は 4KB に制限されています。Clerk のデフォルトクレームが約 2.8KB を使用するため、カスタムクレームに使えるのは 1.2KB です。

⚠️ 開発時の注意:Vite の開発モードでカスタムクレームをテストすると、**「431 Request Header Fields Too Large」**エラーが発生することがあります。これは、Clerk のハンドシェイクトークンが URL 内で Vite の 8KB 制限を超えるためです。解決方法については、Issue #11 を参照してください。

解決方法:

// ✅ GOOD: Minimal claims
{
  "user_id": "{{user.id}}",
  "email": "{{user.primary_email_address}}",
  "role": "{{user.public_metadata.role}}"
}

// ❌ BAD: Exceeds limit
{
  "bio": "{{user.public_metadata.bio}}",  // 6KB field
  "all_metadata": "{{user.public_metadata}}"  // Entire object
}

ベストプラクティス:大きなデータはデータベースに保存し、JWT には識別子やロールのみを含めてください。

TypeScript の型安全性

自動補完を有効にするため、グローバル型宣言を追加します。

types/globals.d.ts を作成します:

export {}

declare global {
  interface CustomJwtSessionClaims {
    metadata: {
      role?: 'admin' | 'moderator' | 'user'
      onboardingComplete?: boolean
      organizationId?: string
    }
  }
}
一般的なユースケース

ロールベースのアクセス制御:

{
  "email": "{{user.primary_email_address}}",
  "role": "{{user.public_metadata.role || 'user'}}",
  "permissions": "{{user.public_metadata.permissions}}"
}

マルチテナントアプリケーション:

{
  "user_id": "{{user.id}}",
  "org_id": "{{user.public_metadata.org_id}}",
  "org_role": "{{user.public_metadata.org_role}}"
}

Supabase との統合:

{
  "email": "{{user.primary_email_address}}",
  "app_metadata": {
    "provider": "clerk"
  },
  "user_metadata": {
    "full_name": "{{user.full_name}}"
  }
}
関連項目
  • 完全なリファレンス:包括的なドキュメントについては、references/jwt-claims-guide.md を参照してください
  • テンプレートの例:動作するサンプルについては、templates/jwt/ ディレクトリを参照してください
  • TypeScript の型:templates/typescript/custom-jwt-types.d.ts を参照してください
  • 公式ドキュメント:https://clerk.com/docs/guides/sessions/jwt-templates

テスト

Clerk は、ローカル開発や CI/CD パイプライン向けに包括的なテストツールを提供しています。

クイックスタート:テスト用認証情報

テスト用メールアドレス(メールは送信されず、OTP は固定です):

[email protected]
[email protected]

テスト用電話番号(SMS は送信されず、OTP は固定です):

+12015550100
+19735550133

固定 OTP コード:424242(すべてのテスト用認証情報で使用できます)

セッショントークンの生成

API エンドポイントのテスト用に、有効なセッショントークン(有効期間 60 秒)を生成します:

# Using the provided script
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js

# Create new test user
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --create-user

# Auto-refresh token every 50 seconds
CLERK_SECRET_KEY=sk_test_... node scripts/generate-session-token.js --refresh

手動のフロー:

  1. ユーザーを作成:POST /v1/users
  2. セッションを作成:POST /v1/sessions
  3. トークンを生成:POST /v1/sessions/{session_id}/tokens
  4. ヘッダーで使用:Authorization: Bearer <token>
Playwright による E2E テスト

Testing Token を自動管理するために @clerk/testing をインストールします:

npm install -D @clerk/testing

グローバルセットアップ(global.setup.ts):

import { clerkSetup } from '@clerk/testing/playwright'
import { test as setup } from '@playwright/test'

setup('global setup', async ({}) => {
  await clerkSetup()
})

テストファイル(auth.spec.ts):

import { setupClerkTestingToken } from '@clerk/testing/playwright'
import { test } from '@playwright/test'

test('sign up', async ({ page }) => {
  await setupClerkTestingToken({ page })

  await page.goto('/sign-up')
  await page.fill('input[name="emailAddress"]', '[email protected]')
  await page.fill('input[name="password"]', 'TestPassword123!')
  await page.click('button[type="submit"]')

  // Verify with fixed OTP
  await page.fill('input[name="code"]', '424242')
  await page.click('button[type="submit"]')

  await expect(page).toHaveURL('/dashboard')
})
Testing Token(ボット検出の回避)

Testing Token を使うと、テストスイートでのボット検出を回避できます。

トークンの取得:

curl -X POST https://api.clerk.com/v1/testing_tokens \
  -H "Authorization: Bearer sk_test_..."

フロントエンド API リクエストでの使用:

POST https://your-app.clerk.accounts.dev/v1/client/sign_ups?__clerk_testing_token=TOKEN

注:Playwright/Cypress では、@clerk/testing がこの処理を自動で行います。

本番環境での制限事項

Testing Token は開発環境と本番環境の両方で使用できますが、以下の制限があります:

  • ❌ コードベースの認証(SMS/メール OTP)は本番環境ではサポートされていません
  • ✅ メールアドレスとパスワードによる認証はサポートされています
  • ✅ マジックリンクはサポートされています
関連項目

既知の問題の防止

このスキルは、ドキュメント化された 11 件の問題を防止します:

問題 #1:Clerk Secret Key の未設定

エラー:「Missing Clerk Secret Key or API Key」 情報源:https://stackoverflow.com/questions/77620604 防止策:必ず `.env.local` に設定するか、`wrangler secret put` を使用してください

問題 #2:API Key から Secret Key への移行

エラー:「apiKey is deprecated, use secretKey」 情報源:https://clerk.com/docs/upgrade-guides/core-2/backend 防止策:すべての呼び出しで `apiKey` を `secretKey` に置き換えてください

問題 #3:JWKS キャッシュの競合状態

エラー:「No JWK available」 情報源:https://github.com/clerk/javascript/blob/main/packages/backend/CHANGELOG.md 防止策:@clerk/[email protected] 以降を使用してください(修正済み)

問題 #4:authorizedParties の未設定(CSRF)

エラー:エラーは発生しませんが、CSRF の脆弱性があります 情報源:https://clerk.com/docs/reference/backend/verify-token 防止策:必ず `authorizedParties: ['https://yourdomain.com']` を設定してください

問題 #5:インポートパスの変更(Core 2)

エラー:「Cannot find module」 情報源:https://clerk.com/docs/upgrade-guides/core-2/backend 防止策:Core 2 向けにインポートパスを更新してください

問題 #6:JWT のサイズ制限超過

エラー:トークンがサイズ制限を超えています 情報源:https://clerk.com/docs/backend-requests/making/custom-session-token 防止策:カスタムクレームは 1.2KB 未満にしてください

問題 #7:API バージョン v1 の非推奨化

エラー:「API version v1 is deprecated」 情報源:https://clerk.com/docs/upgrade-guides/core-2/backend 防止策:最新の SDK バージョン(API v2025-04-10)を使用してください

問題 #8:ClerkProvider JSX コンポーネントのエラー

エラー:「cannot be used as a JSX component」 情報源:https://stackoverflow.com/questions/79265537 防止策:@clerk/[email protected]+ で React 19 との互換性を確保してください

Issue #9:非同期 auth() ヘルパーの混乱

エラー:「auth() is not a function」 出典:https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6 予防策:必ず await します:`const { userId } = await auth()`

Issue #10:環境変数の設定ミス

エラー:「Missing Publishable Key」またはシークレットの漏えい 予防策:正しいプレフィックス(`NEXT_PUBLIC_`、`VITE_`)を使用し、シークレットを絶対にコミットしないでください

Issue #11:431 Request Header Fields Too Large(Vite 開発モード)

エラー:サインイン時に「431 Request Header Fields Too Large」が発生する 出典:カスタム JWT クレームのテスト時に、Vite 開発モードでよく発生します 原因:Clerk の URL 内の `__clerk_handshake` トークンが、Vite の 8KB のヘッダー上限を超えています 予防策:

`package.json` に追加します: ```json { "scripts": { "dev": "NODE_OPTIONS='--max-http-header-size=32768' vite" } } ```

一時的な回避策:ブラウザーのキャッシュを消去し、サインアウトしてから、再度サインインします

理由:Clerk の開発用トークンは本番環境より大きく、カスタム JWT クレームによってハンドシェイクトークンのサイズが増加します

注:これは Issue #6(セッショントークンのサイズ)とは異なります。Issue #6 は Cookie(1.2KB)に関するもので、こちらは開発モードでの URL パラメーター(8KB → 32KB)に関するものです。


重要なルール

必ず行うこと

✅ トークンの検証時に `authorizedParties` を設定する ✅ `CLERK_SECRET_KEY` 環境変数を使用する ✅ 認証 UI をレンダリングする前に `isLoaded` を確認する ✅ リクエストごとに `getToken()` で新しいトークンを取得する ✅ Next.js v6 以降では `auth()` を await する ✅ クライアント変数にのみ `NEXT_PUBLIC_` プレフィックスを使用する ✅ `wrangler secret put` でシークレットを保存する ✅ ルート保護用のミドルウェアを実装する ✅ API バージョン 2025-04-10 以降を使用する

絶対に行わないこと

❌ クライアントコードに `CLERK_SECRET_KEY` を保存する ❌ 非推奨の `apiKey` パラメーターを使用する ❌ トークンを localStorage に保存する ❌ `authorizedParties` のチェックを省略する ❌ カスタム JWT クレームを 1.2KB より大きくする ❌ `isLoaded` の確認を忘れる ❌ `NEXT_PUBLIC_` プレフィックスでシークレットを公開する ❌ API バージョン v1 を使用する


公式ドキュメント


パッケージバージョン(2025-10-22 に確認済み)

```json { "dependencies": { "@clerk/nextjs": "^6.33.3", "@clerk/clerk-react": "^5.51.0", "@clerk/backend": "^2.17.2" } } ```

コメント