mcpField
J
jwt-authentication

jwt-authentication

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

jwt-authentication について

Node.js アプリケーションに JWT 認証を導入するための学習・実装ガイドです。登録、ログイン、保護されたルートに加え、トークン更新やロールベースアクセス制御も扱います。

主な機能

  1. 01JWT の生成と検証
  2. 02ユーザー登録とパスワード確認
  3. 03ミドルウェアによるルート保護
  4. 04トークン更新と有効期限管理
  5. 05ロールベースアクセス制御

活用シーン

  1. 01Node.js REST API への認証追加
  2. 02JWT によるアプリケーションルートの保護
  3. 03トークン更新とアクセス制御フローの構築

インストール

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

$npx skills add https://github.com/pluginagentmarketplace/custom-plugin-nodejs --skill jwt-authentication

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
config.yaml
references/
GUIDE.md
scripts/
helper.py

詳細

JWT 認証スキル

JSON Web Token を使用して、Node.js アプリケーションにセキュアでスケーラブルな認証を実装します。

クイックスタート

JWT 認証を 4 つのステップで実装します。

  1. インストール - npm install jsonwebtoken bcryptjs
  2. 登録 - パスワードをハッシュ化し、ユーザーを作成してトークンを生成します
  3. ログイン - パスワードを検証してトークンを生成します
  4. 保護 - ミドルウェアでトークンを検証します

基本概念

JWT の生成
const jwt = require('jsonwebtoken');

function generateToken(userId) {
  return jwt.sign(
    { id: userId },
    process.env.JWT_SECRET,
    { expiresIn: '1h' }
  );
}

function generateRefreshToken(userId) {
  return jwt.sign(
    { id: userId },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: '7d' }
  );
}
ユーザー登録
const bcrypt = require('bcryptjs');

async function register(req, res) {
  const { email, password, name } = req.body;

  // Check if user exists
  const existingUser = await User.findOne({ email });
  if (existingUser) {
    return res.status(409).json({ error: 'User already exists' });
  }

  // Hash password
  const hashedPassword = await bcrypt.hash(password, 10);

  // Create user
  const user = await User.create({
    email,
    password: hashedPassword,
    name
  });

  // Generate tokens
  const accessToken = generateToken(user._id);
  const refreshToken = generateRefreshToken(user._id);

  res.status(201).json({
    user: { id: user._id, email, name },
    accessToken,
    refreshToken
  });
}
ユーザーログイン
async function login(req, res) {
  const { email, password } = req.body;

  // Find user
  const user = await User.findOne({ email });
  if (!user) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }

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

  // Generate tokens
  const accessToken = generateToken(user._id);
  const refreshToken = generateRefreshToken(user._id);

  res.json({
    user: { id: user._id, email: user.email },
    accessToken,
    refreshToken
  });
}
認証ミドルウェア
async function authenticate(req, res, next) {
  try {
    // Get token from header
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({ error: 'No token provided' });
    }

    const token = authHeader.split(' ')[1];

    // Verify token
    const decoded = jwt.verify(token, process.env.JWT_SECRET);

    // Get user
    const user = await User.findById(decoded.id).select('-password');
    if (!user) {
      return res.status(401).json({ error: 'User not found' });
    }

    req.user = user;
    next();
  } catch (error) {
    res.status(401).json({ error: 'Invalid token' });
  }
}

// Usage
router.get('/profile', authenticate, getProfile);

学習パス

初級(1~2 週間)
  • ✅ JWT の構造を理解する
  • ✅ 登録とログインを実装する
  • ✅ 認証ミドルウェアを作成する
  • ✅ ルートを保護する
中級(3~4 週間)
  • ✅ リフレッシュトークンのフロー
  • ✅ ロールベースのアクセス制御
  • ✅ パスワードリセットのフロー
  • ✅ トークンのブラックリスト化
上級(5~6 週間)
  • ✅ OAuth の統合
  • ✅ 二要素認証
  • ✅ セッション管理
  • ✅ セキュリティのベストプラクティス

高度なパターン

ロールベースのアクセス制御
const authorize = (...roles) => {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({ error: 'Not authenticated' });
    }

    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }

    next();
  };
};

// Usage
router.delete('/users/:id',
  authenticate,
  authorize('admin', 'moderator'),
  deleteUser
);
トークンの更新
async function refreshAccessToken(req, res) {
  const { refreshToken } = req.body;

  try {
    const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);

    // Verify refresh token exists in database
    const stored = await RefreshToken.findOne({
      token: refreshToken,
      userId: decoded.id
    });

    if (!stored) {
      return res.status(401).json({ error: 'Invalid refresh token' });
    }

    // Generate new access token
    const accessToken = generateToken(decoded.id);

    res.json({ accessToken });
  } catch (error) {
    res.status(401).json({ error: 'Token refresh failed' });
  }
}
パスワードリセットのフロー
async function requestPasswordReset(req, res) {
  const { email } = req.body;
  const user = await User.findOne({ email });

  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }

  // Generate reset token (short expiry)
  const resetToken = jwt.sign(
    { id: user._id, purpose: 'reset' },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );

  // Send email with reset link
  await sendResetEmail(user.email, resetToken);

  res.json({ message: 'Reset email sent' });
}

async function resetPassword(req, res) {
  const { token, newPassword } = req.body;

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);

    if (decoded.purpose !== 'reset') {
      return res.status(400).json({ error: 'Invalid token' });
    }

    const hashedPassword = await bcrypt.hash(newPassword, 10);
    await User.findByIdAndUpdate(decoded.id, { password: hashedPassword });

    res.json({ message: 'Password reset successful' });
  } catch (error) {
    res.status(400).json({ error: 'Invalid or expired token' });
  }
}

セキュリティのベストプラクティス

  • ✅ 強力な JWT シークレットを使用します(32 文字以上のランダムな文字列)
  • ✅ アクセストークンの有効期限を短く設定します(15 分~1 時間)
  • ✅ リフレッシュトークンの有効期限を長めに設定します(7 日~30 日)
  • ✅ リフレッシュトークンをデータベースに保存します
  • ✅ bcrypt でパスワードをハッシュ化します(10 ラウンド以上)
  • ✅ 本番環境では HTTPS を使用します
  • ✅ レート制限を実装します
  • ✅ すべての入力を検証します
  • ✅ 機密データを JWT ペイロードに保存しないでください

JWT の構造

header.payload.signature

Header (base64):
{
  "alg": "HS256",
  "typ": "JWT"
}

Payload (base64):
{
  "id": "user123",
  "iat": 1516239022,
  "exp": 1516242622
}

Signature:
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

一般的な JWT クレーム

  • iss - 発行者
  • sub - サブジェクト(ユーザー ID)
  • aud - 対象者
  • exp - 有効期限
  • iat - 発行日時
  • nbf - 有効期間の開始日時

使用する場面

次のような場合に JWT 認証を使用します。

  • ステートレスな REST API を構築する場合
  • スケーラビリティが必要な場合(サーバー側のセッションなし)
  • モバイルアプリの認証
  • マイクロサービスアーキテクチャ
  • シングルサインオン(SSO)

関連スキル

  • Express REST API(API エンドポイントを保護)
  • データベース統合(ユーザーを保存)
  • テストとデバッグ(認証フローをテスト)
  • パフォーマンス最適化(トークンのキャッシュ)

リソース

コメント