Use Cases

Claude CodeでJWT認証を設計・実装するベストプラクティス

Claude Codeを使ったJWT認証の設計パターンと実装方法を解説。アクセストークン・リフレッシュトークンの管理、セキュリティ対策まで網羅。

JWT認証の基本設計

JWT(JSON Web Token)はステートレスな認証を実現するトークン形式です。Claude Codeを使えば、セキュアなJWT認証基盤を効率的に構築できます。

トークン生成と検証

import jwt from "jsonwebtoken";
import { z } from "zod";

const TokenPayloadSchema = z.object({
  userId: z.string(),
  email: z.string().email(),
  role: z.enum(["admin", "user", "viewer"]),
});

type TokenPayload = z.infer<typeof TokenPayloadSchema>;

const JWT_CONFIG = {
  accessSecret: process.env.JWT_ACCESS_SECRET!,
  refreshSecret: process.env.JWT_REFRESH_SECRET!,
  accessExpiresIn: "15m" as const,
  refreshExpiresIn: "7d" as const,
};

function generateTokens(payload: TokenPayload) {
  const accessToken = jwt.sign(payload, JWT_CONFIG.accessSecret, {
    expiresIn: JWT_CONFIG.accessExpiresIn,
    issuer: "my-app",
    audience: "my-app-client",
  });

  const refreshToken = jwt.sign(
    { userId: payload.userId },
    JWT_CONFIG.refreshSecret,
    {
      expiresIn: JWT_CONFIG.refreshExpiresIn,
      issuer: "my-app",
    }
  );

  return { accessToken, refreshToken };
}

function verifyAccessToken(token: string): TokenPayload {
  const decoded = jwt.verify(token, JWT_CONFIG.accessSecret, {
    issuer: "my-app",
    audience: "my-app-client",
  });
  return TokenPayloadSchema.parse(decoded);
}

認証ミドルウェア

import { Request, Response, NextFunction } from "express";

interface AuthenticatedRequest extends Request {
  user?: TokenPayload;
}

function authMiddleware(
  req: AuthenticatedRequest,
  res: Response,
  next: NextFunction
) {
  const authHeader = req.headers.authorization;

  if (!authHeader?.startsWith("Bearer ")) {
    return res.status(401).json({ error: "No token provided" });
  }

  const token = authHeader.slice(7);

  try {
    const payload = verifyAccessToken(token);
    req.user = payload;
    next();
  } catch (error) {
    if (error instanceof jwt.TokenExpiredError) {
      return res.status(401).json({
        error: "Token expired",
        code: "TOKEN_EXPIRED",
      });
    }
    return res.status(401).json({ error: "Invalid token" });
  }
}

リフレッシュトークンのローテーション

セキュリティを高めるため、リフレッシュ時に新しいリフレッシュトークンを発行します。

import { Redis } from "ioredis";

const redis = new Redis(process.env.REDIS_URL!);

async function refreshAccessToken(refreshToken: string) {
  // リフレッシュトークンが無効化されていないか確認
  const isRevoked = await redis.get(`revoked:${refreshToken}`);
  if (isRevoked) {
    throw new Error("Refresh token has been revoked");
  }

  const decoded = jwt.verify(refreshToken, JWT_CONFIG.refreshSecret) as {
    userId: string;
  };

  // ユーザー情報を取得
  const user = await getUserById(decoded.userId);
  if (!user) {
    throw new Error("User not found");
  }

  // 古いリフレッシュトークンを無効化
  await redis.set(
    `revoked:${refreshToken}`,
    "1",
    "EX",
    7 * 24 * 60 * 60
  );

  // 新しいトークンペアを生成
  const payload: TokenPayload = {
    userId: user.id,
    email: user.email,
    role: user.role,
  };

  return generateTokens(payload);
}

ログインエンドポイント

import bcrypt from "bcrypt";

app.post("/auth/login", async (req, res) => {
  const { email, password } = req.body;

  const user = await getUserByEmail(email);
  if (!user) {
    return res.status(401).json({ error: "Invalid credentials" });
  }

  const isValid = await bcrypt.compare(password, user.passwordHash);
  if (!isValid) {
    return res.status(401).json({ error: "Invalid credentials" });
  }

  const payload: TokenPayload = {
    userId: user.id,
    email: user.email,
    role: user.role,
  };

  const tokens = generateTokens(payload);

  // リフレッシュトークンをHttpOnly Cookieに設定
  res.cookie("refreshToken", tokens.refreshToken, {
    httpOnly: true,
    secure: true,
    sameSite: "strict",
    maxAge: 7 * 24 * 60 * 60 * 1000,
  });

  res.json({ accessToken: tokens.accessToken });
});

セキュリティ上の注意点

JWT認証で特に注意すべきポイントです。セキュリティの全体設計についてはOAuth認証の実装も参照してください。

リスク対策
トークン漏洩短い有効期限 + リフレッシュトークン
XSSHttpOnly Cookie + CSP
CSRFSameSite属性 + CSRFトークン
リプレイ攻撃jtiクレーム + ブラックリスト

Claude Codeでの活用

プロジェクトの既存コードに合わせたJWT認証を実装する際は、以下のようにClaude Codeに指示します。生産性を上げるコツはClaude Codeの生産性を3倍にする10のTipsで解説しています。

JWT認証を実装して。
- アクセストークン: 15分、リフレッシュトークン: 7日
- リフレッシュトークンローテーション対応
- Redisでトークンのブラックリスト管理
- 既存のユーザーモデルと統合して

JWTの詳細仕様はRFC 7519、Claude Codeの使い方は公式ドキュメントを参照してください。

まとめ

JWT認証はステートレスな設計が魅力ですが、トークン管理とセキュリティ対策が重要です。Claude Codeでプロジェクト全体を把握した上で実装すれば、一貫性のある認証基盤を構築できます。

#Claude Code #JWT #認証 #セキュリティ #Node.js