mcpField
A
authentication

authentication

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

authentication について

authentication は、さまざまな Web スタックで認証を計画・実装するスキルです。既存実装の調査からフレームワーク別の設定、セキュリティ確認、テストまでを案内し、特定のライブラリに固定せずプロジェクトに合わせます。

主な機能

  1. 01既存の認証パターンとスタックの検出
  2. 02フレームワーク別の認証ファイル計画
  3. 03セッション、OAuth、ルート保護の案内
  4. 04シークレットとセキュリティ設定の確認
  5. 05テストケース生成とチェックリスト実行

活用シーン

  1. 01ログインと登録フローの追加
  2. 02ルートと API エンドポイントの保護
  3. 03OAuth またはセッション管理の導入
  4. 04認証実装の監査

インストール

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

$npx skills add https://github.com/mgd34msu/goodvibes-plugin --skill authentication

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

同梱ファイルreferences/decision-tree.mdscripts/auth-checklist.sh

詳細

リソース

scripts/
  auth-checklist.sh
references/
  decision-tree.md

認証実装ワークフロー

このスキルは、調査からテストまで、認証の実装を一貫して進めます。ライブラリ固有のスキル(clerk、nextauth、lucia、auth0、firebase-auth、supabase-auth、passport)を、スタックに合わせて適応する統一ワークフローに置き換えます。

このスキルを使用するタイミング

以下を実装する場合に使用します。

  • ユーザーのログインおよびサインアップのフロー
  • セッション管理(Cookie、JWT、サーバーサイドセッション)
  • OAuth 統合(Google、GitHub など)
  • 保護されたルートと API エンドポイント
  • ミドルウェアベースの認証
  • ロールベースのアクセス制御(RBAC)
  • トークンの更新メカニズム
  • パスワードリセットのフロー

前提条件

開始する前に、以下を確認してください。

  1. プロジェクトのフレームワークを把握していること(Next.js、Remix、Express など)
  2. データベースを使用する認証の場合、データベーススキーマを計画していること
  3. 認証方式を把握していること(マネージドサービスかセルフホストか)
  4. 環境変数の設定にアクセスできること

ワークフローの手順

ステップ 1:調査

discover を使用して、既存の認証パターンを把握します。

discover:
  queries:
    - id: existing-auth
      type: grep
      pattern: "(useAuth|getSession|withAuth|requireAuth|protect|authenticate)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: middleware-files
      type: glob
      patterns:
        - "**/middleware.{ts,js}"
        - "**/auth/**/*.{ts,js}"
        - "**/_middleware.{ts,js}"
    - id: session-handling
      type: grep
      pattern: "(session|jwt|token|cookie)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: protected-routes
      type: grep
      pattern: "(protected|private|requireAuth|withAuth)"
      glob: "**/*.{ts,tsx,js,jsx}"
  verbosity: files_only

確認する項目:

  • 既存の認証フック、ユーティリティ、またはミドルウェア
  • セッションの保存方法(Cookie、localStorage、サーバーサイド)
  • 保護されたルートのパターン
  • 認証プロバイダーの設定(サードパーティを使用している場合)

判断ポイント: 認証がすでに部分的に実装されている場合は、拡張する前に既存のファイルを読んでパターンを把握してください。

ステップ 2:スタックの検出

detect_stack を使用してフレームワークを特定し、認証方式を判断します。

detect_stack:
  path: "."

フレームワークの検出:

  • Next.js(App Router):middleware.ts + Server Actions + cookies を使用します
  • Next.js(Pages Router):getServerSideProps + API routes + NextAuth を使用します
  • Remix:loader/action 認証 + セッション Cookie を使用します
  • Express/Fastify:ミドルウェア + セッションストアを使用します
  • tRPC:コンテキスト + ミドルウェアを使用します
  • GraphQL:コンテキスト + ディレクティブを使用します

判断ツリーを参照: references/decision-tree.md を読んで、フレームワークと要件に基づき、マネージド(Clerk、Auth0)、セルフホスト(NextAuth、Lucia)、サーバーレス(Supabase Auth)のいずれかを選択します。

ステップ 3:実装計画

フレームワークと判断ツリーに基づき、作成または変更するファイルを計画します。

必要となる一般的なファイル:

  1. ミドルウェア(middleware.ts、auth.middleware.ts)

    • リクエストをインターセプトします
    • 認証状態を確認します
    • 未認証ユーザーをリダイレクトします
  2. 認証ユーティリティ(lib/auth.ts、utils/auth.ts)

    • セッションの作成/検証
    • トークンの生成/検証
    • パスワードのハッシュ化(bcrypt、argon2)
  3. 認証 API ルート(/api/auth/login、/api/auth/signup、/api/auth/logout)

    • 認証リクエストを処理します
    • セッション Cookie を設定します
    • 認証状態を返します
  4. 保護されたルートのラッパー(withAuth、requireAuth)

    • HOC またはサーバーユーティリティ
    • レンダリング前に認証を確認します
    • リダイレクトするか 401 を返します
  5. クライアントフック(useAuth、useSession)

    • 現在のユーザーにアクセスします
    • クライアント側の認証状態を管理します
    • ログイン/ログアウトを実行します

フレームワーク固有のパターン:

Next.js App Router:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('session')?.value;
  
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*', '/api/:path*']
};

Remix:

// app/utils/session.server.ts
import { createCookieSessionStorage } from '@remix-run/node';

const { getSession, commitSession, destroySession } =
  createCookieSessionStorage({
    cookie: {
      name: '__session',
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      secrets: [process.env.SESSION_SECRET],
      sameSite: 'lax'
    }
  });

export { getSession, commitSession, destroySession };

Express:

// middleware/auth.ts
import jwt from 'jsonwebtoken';
import type { Request, Response, NextFunction } from 'express';

export function requireAuth(req: Request, res: Response, next: NextFunction) {
  const token = req.headers.authorization?.replace(/^bearer\s+/i, '');
  
  if (!token) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET!);
    req.user = payload;
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}
ステップ 4:設定とコアファイルの作成

precision_write をバッチモードで使用し、認証インフラストラクチャを作成します。

precision_write:
  files:
    - path: "middleware.ts"
      content: |
        # Framework-specific middleware (see patterns above)
    - path: "lib/auth.ts"
      content: |
        # Session validation, token generation
    - path: "app/api/auth/login/route.ts"
      content: |
        # Login endpoint implementation
    - path: "app/api/auth/signup/route.ts"
      content: |
        # Sign-up endpoint with validation
    - path: "app/api/auth/logout/route.ts"
      content: |
        # Logout and session cleanup
  verbosity: minimal

重要:プレースホルダーを使用しない

  • 検証を完全に実装します(zod、yup など)
  • 適切なエラーハンドリングを含めます
  • bcrypt/argon2 でパスワードをハッシュ化します
  • セキュアなセッション設定を使用します
  • 該当する場合は CSRF 保護を追加します
ステップ 5:依存関係のインストール

precision_exec を使用して、必要なパッケージをインストールします。

precision_exec:
  commands:
    # For JWT-based auth
    - cmd: "npm install jsonwebtoken bcryptjs"
    - cmd: "npm install -D @types/jsonwebtoken @types/bcryptjs"
    
    # For session-based auth
    - cmd: "npm install express-session connect-redis"
    - cmd: "npm install -D @types/express-session"
    
    # For managed services
    - cmd: "npm install @clerk/nextjs"  # Clerk
    - cmd: "npm install next-auth"      # NextAuth
    - cmd: "npm install better-auth"    # Better Auth (replaces deprecated Lucia)
  verbosity: minimal

データベースのマイグレーションを実行する(必要な場合):

precision_exec:
  commands:
    - cmd: "npx prisma migrate dev --name add_user_auth"
      timeout_ms: 60000
    - cmd: "npx prisma generate"
  verbosity: standard
ステップ 6:セキュリティ検証

analysis-engine のツールを使用して、セキュリティを検証します。

1. ハードコードされたシークレットをスキャンする:

scan_for_secrets:
  paths:
    - "lib/auth.ts"
    - "app/api/auth/**/*.ts"
    - "middleware.ts"

**期待される結果:**シークレットが 0 件検出されます。すべての API キー、JWT シークレット、認証情報は .env ファイルに保存する必要があります。

シークレットが検出された場合:

  • .env または .env.local に移動します
  • アクセスには process.env.VAR_NAME を使用します
  • まだ追加されていない場合は、.gitignore に追加します

2. 環境変数を監査する:

env_audit:
  check_documented: true

**期待される結果:**認証関連の環境変数がすべて .env.example または README に記載されています。

必要な変数(一般的な例):

  • JWT_SECRET または SESSION_SECRET
  • DATABASE_URL(データベースを使用する場合)
  • OAuth 認証情報(GOOGLE_CLIENT_ID、GITHUB_CLIENT_SECRET など)
  • NEXTAUTH_URL と NEXTAUTH_SECRET(NextAuth 用)

3. 実装を検証する:

# Use precision_grep to validate critical security patterns
precision_grep:
  queries:
    - id: password_hashing
      pattern: "bcrypt|argon2|hashPassword"
      path: "lib"
      glob: "**/*.ts"
    - id: httpOnly_cookies
      pattern: "httpOnly.*true|httpOnly:\s*true"
      path: "."
      glob: "**/*.ts"
    - id: csrf_protection
      pattern: "csrf|CsrfToken|verifyCsrfToken"
      path: "."
      glob: "**/*.ts"
  output:
    format: "count_only"
ステップ 7:保護されたルートの実装

ルート保護ユーティリティを作成します。

サーバーサイド保護(Next.js App Router):

// lib/auth.ts
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

export async function requireAuth() {
  const cookieStore = await cookies();
  const session = cookieStore.get('session')?.value;
  
  if (!session) {
    redirect('/login');
  }
  
  const user = await validateSession(session);
  if (!user) {
    redirect('/login');
  }
  
  return user;
}

クライアントサイドのフック(React):

// hooks/useAuth.ts
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';

export function useAuth(options?: { redirectTo?: string }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const router = useRouter();
  
  useEffect(() => {
    fetch('/api/auth/me')
      .then(res => res.ok ? res.json() : null)
      .then(data => {
        if (!data && options?.redirectTo) {
          router.push(options.redirectTo);
        } else {
          setUser(data);
        }
      })
      .finally(() => setLoading(false));
  }, [options?.redirectTo, router]);
  
  return { user, loading };
}

ルートに適用する:

precision_edit を使用して、既存のルートに認証チェックを追加します。

precision_edit:
  files:
    - path: "app/dashboard/page.tsx"
      edits:
        - find: "export default function DashboardPage()"
          replace: |
            export default async function DashboardPage() {
              const user = await requireAuth();
          hints:
            near_line: 1
ステップ 8:実装をテストする

suggest_test_cases を使用して、認証に特化したテストシナリオを生成します。

suggest_test_cases:
  file: "lib/auth.ts"
  category: "authentication"

期待されるテストケース:

  • 正しい認証情報でログインできる
  • 誤ったパスワードでログインに失敗する
  • 有効なデータでサインアップできる
  • 重複したメールアドレスでサインアップに失敗する
  • 未認証ユーザーが保護されたルートにアクセスするとリダイレクトされる
  • セッショントークンが更新される
  • ログアウトするとセッションが消去される
  • CSRF トークンが検証される
  • パスワードリセットのフローが動作する

検証スクリプトを実行する:

bash scripts/auth-checklist.sh .

**期待される終了コード:**0(すべてのチェックに合格)

手動テストのチェックリスト:

  1. 新しいユーザーをサインアップする
  2. データベース内でパスワードがハッシュ化されていることを確認する
  3. 認証情報を使ってログインする
  4. 保護されたルートにアクセスする(成功するはずです)
  5. ログアウトする
  6. 保護されたルートにアクセスする(ログイン画面にリダイレクトされるはずです)
  7. OAuth フローをテストする(実装されている場合)
  8. ページの再読み込み後もセッションが維持されることを確認する
  9. トークンの有効期限切れと更新をテストする

フレームワーク別の一般的なパターン

Next.js(App Router)

セッション管理:

  • 'next/headers' の cookies() を使用します
  • httpOnly、secure、sameSite を設定した Cookie を使用します
  • middleware.ts とサーバーコンポーネントで検証します

保護されたルート:

  • サーバーサイド:page/layout で await requireAuth() を呼び出します
  • クライアントサイド:redirectTo を指定して useAuth() フックを使用します
  • API ルート:ルートハンドラーで Cookie を確認します

OAuth:

  • 手軽さを重視する場合は NextAuth を使用します
  • または、リダイレクト URI を使った OAuth フローを手動で実装します
Remix

セッション管理:

  • createCookieSessionStorage を使用します
  • loaders で検証します
  • actions でセッションをコミットします

保護されたルート:

  • loader でセッションを確認し、未認証の場合は redirect() をスローします
  • getSession() ユーティリティを一貫して使用します

OAuth:

  • remix-auth のストラテジーを使用します
  • 専用ルートでコールバックを処理します
Express/Fastify

セッション管理:

  • express-session と Redis ストアを使用します
  • または Authorization ヘッダー内の JWT トークンを使用します

保護されたルート:

  • requireAuth、optionalAuth などのミドルウェア関数を使用します
  • 特定のルートまたは全体に適用します

OAuth:

  • passport.js のストラテジーを使用します
  • ユーザーのシリアライズ/デシリアライズを設定します

エラー処理

認証の失敗には、エラーリカバリープロトコルに従ってください。

ログインの失敗
try {
  const user = await validateCredentials(email, password);
  await createSession(user.id);
  return { success: true };
} catch (err) {
  if (err instanceof InvalidCredentialsError) {
    // Don't leak whether email exists
    return { error: 'Invalid email or password' };
  }
  if (err instanceof UserLockedError) {
    return { error: 'Account locked. Contact support.' };
  }
  throw err; // Unexpected error
}
セッション検証の失敗
export async function validateSession(token: string) {
  try {
    const payload = jwt.verify(token, process.env.JWT_SECRET!);
    return await getUserById(payload.userId);
  } catch (err) {
    if (err instanceof jwt.TokenExpiredError) {
      return null; // Let caller handle (refresh or re-login)
    }
    if (err instanceof jwt.JsonWebTokenError) {
      return null; // Invalid token
    }
    throw err; // Unexpected error
  }
}
データベースエラー
try {
  const user = await db.user.create({
    data: { email, passwordHash }
  });
} catch (err) {
  if (err.code === 'P2002') {
    // Prisma unique constraint violation
    return { error: 'Email already registered' };
  }
  throw err;
}

セキュリティチェックリスト

実装を完了とする前に、以下を確認してください。

  • パスワードが bcrypt(コスト 10 以上)または argon2 でハッシュ化されている
  • セッショントークンがランダム(crypto.randomBytes)または署名済み JWT である
  • Cookie が httpOnly、secure(本番環境)、sameSite: 'lax' または 'strict' に設定されている
  • CSRF 保護が有効になっている(Cookie ベースの認証の場合)
  • ログイン/サインアップのエンドポイントにレート制限が設定されている
  • すべての認証エンドポイントで入力が検証されている
  • エラーメッセージに機密データが含まれていない
  • 環境変数が .env.example に記載されている
  • ソースコードにシークレットがハードコードされていない
  • セッションの有効期限が設定されている(一般的には 1~7 日)
  • ログアウト時にすべての認証トークン/セッションが消去される
  • OAuth のリダイレクト URI が許可リストに登録されている

参考資料

  • references/decision-tree.md - マネージド、セルフホスト可能、サーバーレスの比較
  • .goodvibes/memory/patterns.json - プロジェクト固有の認証パターン
  • scripts/auth-checklist.sh - 自動検証スクリプト

トラブルシューティング

「リクエスト間でセッションが保持されない」

考えられる原因:

  • Cookie が設定されていない(レスポンスヘッダーを確認してください)
  • httpOnly によりクライアント側からアクセスできない(想定どおりです)
  • sameSite: 'strict' によりクロスオリジン通信がブロックされている('lax' を使用してください)
  • Cookie のドメインが一致していない

修正方法:

  1. 認証コードの Cookie 設定を確認します
  2. レスポンスに Cookie が含まれていることを確認します:precision_exec: { cmd: "curl -v localhost:3000/api/auth/login" }
  3. ミドルウェアが Cookie を正しく読み取っていることを確認します
「サーバー再起動後に JWT トークンが無効になる」

考えられる原因:

  • 再起動のたびに JWT_SECRET が変わる
  • .env ファイルにシークレットがない
  • 環境によってシークレットが異なる

修正方法:

  1. JWT_SECRET を .env に移します:JWT_SECRET=<random-256-bit-hex>
  2. 次のコマンドで生成します:openssl rand -hex 32
  3. .env を git にコミットしないでください
「OAuth コールバックが redirect_uri_mismatch で失敗する」

考えられる原因:

  • OAuth プロバイダーのダッシュボードでコールバック URL が許可リストに登録されていない
  • http と https が一致していない
  • ポート番号が指定されていない

修正方法:

  1. OAuth プロバイダーの設定を確認します
  2. エラーに表示されているとおりのコールバック URL を追加します
  3. ローカル開発では、http://localhost:3000/api/auth/callback/google を使用します(例)
「保護されたルートでリダイレクトされない」

考えられる原因:

  • ミドルウェアが正しく設定されていない
  • Matcher パターンがルートと一致しない
  • セッションの検証が失敗しているが、エラーが表示されない

修正方法:

  1. middleware.ts の config.matcher を確認します
  2. ミドルウェアにログを追加し、実行されていることを確認します
  3. セッションの検証を個別にテストします

実装後の次のステップ

  1. ロールベースのアクセス制御(RBAC)を追加する:

    • User モデルに role フィールドを追加する
    • 権限チェック用のユーティリティを作成する
    • 管理者用ルートを保護する
  2. パスワードリセットを実装する:

    • リセットトークンを生成する
    • リセットリンクを含むメールを送信する
    • トークンを検証し、パスワードを更新する
  3. メール認証を追加する:

    • サインアップ時に認証トークンを生成する
    • 認証メールを送信する
    • トークンを検証し、ユーザーを認証済みとしてマークする
  4. リフレッシュトークンを設定する:

    • 有効期間の短いアクセス トークンを発行する(15 min)
    • 有効期間の長いリフレッシュトークンを発行する(7 days)
    • リフレッシュトークンの使用時にローテーションする
  5. 監査ログを追加する:

    • すべてのログイン試行(成功と失敗)を記録する
    • IP アドレスとユーザーエージェントを追跡する
    • 不審なアクティビティを監視する

まとめ

このワークフローでは、次のことが可能です。

  • フレームワークに依存しない認証の実装
  • 検証を重視したセキュリティファーストのアプローチ
  • GoodVibes の精密ツールとの統合
  • スクリプトによる自動検証
  • エラー処理とトラブルシューティング

各ステップを順番に進め、すべてのファイル操作と検証に精密ツールを使用してください。

コメント