clerk-auth について
clerk-auth は、Clerk 認証の実装ガイドです。React、Next.js、Cloudflare Workers を使う開発者向けに、アプリ設定、ルート保護、トークン検証、カスタム JWT クレーム、テストを扱います。
主な機能
- 01React と Next.js の認証設定
- 02アプリのルート保護
- 03Cloudflare Workers でのトークン検証
- 04カスタム JWT クレームの作成
- 05提供された認証情報でのテスト
活用シーン
- 01React や Next.js アプリへのサインイン追加
- 02未認証リクエストからのルート保護
- 03Cloudflare Workers でのセッショントークン確認
- 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) - ClerkProvider + フック
- Next.js App Router - ミドルウェア + 非同期の auth()
- Cloudflare Workers - バックエンドでの検証
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>, ) ```
重要:
- Vite の環境変数には `VITE_` プレフィックスを使用します
- ClerkProvider はアプリ全体をラップする必要があります
- ソース:https://clerk.com/docs/references/react/clerk-provider
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
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 に確認済み)
- v6 の新機能:非同期 auth() ヘルパー、Next.js 15 のサポート、デフォルトでの静的レンダリング
- ソース:https://clerk.com/changelog/2024-10-22-clerk-nextjs-v6
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 ```
重要:
- `CLERK_SECRET_KEY` をクライアントに絶対に公開しないでください
- クライアント側の変数にのみ `NEXT_PUBLIC_` プレフィックスを使用してください
- ソース:https://clerk.com/docs/guides/development/clerk-environment-variables
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 ```
最新バージョン:
- @clerk/[email protected](2025-10-22に確認)
- [email protected]
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
重要:
- CSRF 攻撃を防ぐため、必ず
authorizedPartiesを設定してください - 非推奨の
apiKeyではなく、secretKeyを使用してください - 出典:https://clerk.com/docs/reference/backend/verify-token
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
手動のフロー:
- ユーザーを作成:
POST /v1/users - セッションを作成:
POST /v1/sessions - トークンを生成:
POST /v1/sessions/{session_id}/tokens - ヘッダーで使用:
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)は本番環境ではサポートされていません
- ✅ メールアドレスとパスワードによる認証はサポートされています
- ✅ マジックリンクはサポートされています
関連項目
- 完全なガイド:包括的なテストドキュメントについては、
references/testing-guide.mdを参照してください - セッショントークンスクリプト:
scripts/generate-session-token.jsを参照してください - デモリポジトリ:https://github.com/clerk/clerk-playwright-nextjs
- 公式ドキュメント:https://clerk.com/docs/guides/development/testing/overview
既知の問題の防止
このスキルは、ドキュメント化された 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 を使用する
公式ドキュメント
- Clerk ドキュメント:https://clerk.com/docs
- Next.js ガイド:https://clerk.com/docs/references/nextjs/overview
- React ガイド:https://clerk.com/docs/references/react/overview
- バックエンド SDK:https://clerk.com/docs/reference/backend/overview
- JWT テンプレート:https://clerk.com/docs/guides/sessions/jwt-templates
- shadcn/ui との統合:https://clerk.com/docs/guides/development/shadcn-cli
- Context7 ライブラリ ID:`/clerk/clerk-docs`
パッケージバージョン(2025-10-22 に確認済み)
```json { "dependencies": { "@clerk/nextjs": "^6.33.3", "@clerk/clerk-react": "^5.51.0", "@clerk/backend": "^2.17.2" } } ```