Agent Skills by ALSEL
Anthropic Claudeセキュリティ⭐ リポ 0品質スコア 50/100

oauth-implementation

OAuth 2.0 および OAuth 2.1 の認証フローを、PKCEを含むセキュリティベストプラクティスに従って実装する際のガイドラインを提供します。OAuth対応機能の設計・実装時にトリガーされ、安全な認証基盤の構築をサポートします。

description の原文を見る

Guidelines for implementing OAuth 2.0 and OAuth 2.1 authentication flows with security best practices and PKCE

SKILL.md 本文

OAuth 実装

OAuth 2.0 と OAuth 2.1 実装の専門家です。OAuth 認証フローを実装する際は、以下のガイドラインに従ってください。

コア原則

  • 常に OAuth 2.1 パターンを使用してください (PKCE は必須、implicit flow は禁止)
  • すべての OAuth 通信に HTTPS を使用
  • CSRF 保護のための適切な state 管理を実装
  • スコープについて最小権限の原則に従う
  • すべてのトークンはサーバー側で検証

OAuth 2.1 主要要件

OAuth 2.1 はベストプラクティスをまとめ、セキュアでないパターンを廃止しています:

  • PKCE は認可コードフローを使用するすべてのクライアントで必須
  • Implicit grant は廃止
  • Resource Owner Password Credentials grant は廃止
  • Redirect URI は完全一致で検証する必要があります
  • Refresh token は送信者制約またはローテーションを使用する必要があります

Authorization Code Flow with PKCE

ステップ 1: PKCE パラメータの生成

// 暗号的に安全なコード検証機を生成
function generateCodeVerifier() {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return base64URLEncode(array);
}

// 検証機からコードチャレンジを作成
async function generateCodeChallenge(verifier) {
  const encoder = new TextEncoder();
  const data = encoder.encode(verifier);
  const digest = await crypto.subtle.digest('SHA-256', data);
  return base64URLEncode(new Uint8Array(digest));
}

function base64URLEncode(buffer) {
  return btoa(String.fromCharCode(...buffer))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
}

ステップ 2: 認可リクエスト

async function initiateOAuthFlow() {
  const codeVerifier = generateCodeVerifier();
  const codeChallenge = await generateCodeChallenge(codeVerifier);
  const state = generateSecureRandomString();

  // 後で検証するために保存
  sessionStorage.setItem('oauth_code_verifier', codeVerifier);
  sessionStorage.setItem('oauth_state', state);

  const params = new URLSearchParams({
    response_type: 'code',
    client_id: CLIENT_ID,
    redirect_uri: REDIRECT_URI,
    scope: 'openid profile email',
    state: state,
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
  });

  window.location.href = `${AUTHORIZATION_ENDPOINT}?${params}`;
}

ステップ 3: コールバック処理とトークン交換

async function handleCallback() {
  const params = new URLSearchParams(window.location.search);
  const code = params.get('code');
  const state = params.get('state');
  const error = params.get('error');

  // エラーをチェック
  if (error) {
    throw new Error(`OAuth error: ${error} - ${params.get('error_description')}`);
  }

  // CSRF を防ぐために state を検証
  const storedState = sessionStorage.getItem('oauth_state');
  if (state !== storedState) {
    throw new Error('Invalid state parameter - possible CSRF attack');
  }

  // コード検証機を取得
  const codeVerifier = sessionStorage.getItem('oauth_code_verifier');

  // コードをトークンに交換
  const response = await fetch(TOKEN_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code: code,
      redirect_uri: REDIRECT_URI,
      client_id: CLIENT_ID,
      code_verifier: codeVerifier,
    }),
  });

  if (!response.ok) {
    throw new Error('Token exchange failed');
  }

  const tokens = await response.json();

  // クリーンアップ
  sessionStorage.removeItem('oauth_code_verifier');
  sessionStorage.removeItem('oauth_state');

  return tokens;
}

サーバー側の実装

Confidential Client トークン交換

// Node.js/Express の例
app.post('/oauth/callback', async (req, res) => {
  const { code, state } = req.body;

  // state を検証
  if (state !== req.session.oauthState) {
    return res.status(400).json({ error: 'Invalid state' });
  }

  try {
    const tokenResponse = await fetch(TOKEN_ENDPOINT, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        // Confidential clients のクライアント認証
        Authorization: `Basic ${Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64')}`,
      },
      body: new URLSearchParams({
        grant_type: 'authorization_code',
        code: code,
        redirect_uri: REDIRECT_URI,
        code_verifier: req.session.codeVerifier,
      }),
    });

    const tokens = await tokenResponse.json();

    // トークンをサーバー側で安全に保存
    req.session.accessToken = tokens.access_token;
    req.session.refreshToken = tokens.refresh_token;

    res.redirect('/dashboard');
  } catch (error) {
    res.status(500).json({ error: 'Token exchange failed' });
  }
});

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

Access Token の検証

const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

const client = jwksClient({
  jwksUri: `${ISSUER}/.well-known/jwks.json`,
  cache: true,
  cacheMaxAge: 600000, // 10 分
});

function getSigningKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    if (err) return callback(err);
    const signingKey = key.getPublicKey();
    callback(null, signingKey);
  });
}

async function validateToken(token) {
  return new Promise((resolve, reject) => {
    jwt.verify(
      token,
      getSigningKey,
      {
        audience: EXPECTED_AUDIENCE,
        issuer: EXPECTED_ISSUER,
        algorithms: ['RS256'], // 許可されたアルゴリズムをホワイトリスト化
      },
      (err, decoded) => {
        if (err) reject(err);
        else resolve(decoded);
      }
    );
  });
}

Refresh Token ローテーション

async function refreshAccessToken(refreshToken) {
  const response = await fetch(TOKEN_ENDPOINT, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams({
      grant_type: 'refresh_token',
      refresh_token: refreshToken,
      client_id: CLIENT_ID,
    }),
  });

  if (!response.ok) {
    // Refresh token が期限切れまたは取り消されている可能性があります
    throw new Error('Refresh token invalid');
  }

  const tokens = await response.json();

  // ローテーションが有効な場合、新しい refresh token が返されます
  // 新しい refresh token を保存し、古いものを無効化
  return tokens;
}

セキュリティ要件

Redirect URI の検証

// サーバー側: redirect URI をホワイトリストに対して検証
const ALLOWED_REDIRECT_URIS = [
  'https://myapp.com/callback',
  'https://myapp.com/oauth/callback',
];

function validateRedirectUri(uri) {
  // 完全一致 - ワイルドカードなし
  return ALLOWED_REDIRECT_URIS.includes(uri);
}

スコープ管理

// 必要最小限のスコープをリクエスト
const SCOPES = {
  basic: 'openid profile email',
  readOnly: 'openid profile email read:data',
  fullAccess: 'openid profile email read:data write:data',
};

// サーバー側でスコープを検証
function validateScopes(requestedScopes, allowedScopes) {
  const requested = requestedScopes.split(' ');
  const allowed = allowedScopes.split(' ');
  return requested.every(scope => allowed.includes(scope));
}

防止すべき一般的な脆弱性

1. 認可コードインジェクション

常に PKCE を使用してください - code_verifier は元のリクエスター のみがコードを交換できることを保証します。

2. CSRF 攻撃

// 常に state パラメータを使用して検証
const state = crypto.randomBytes(32).toString('hex');
// セッションに保存してコールバックで検証

3. オープンリダイレクト

// ユーザー入力から redirect URI を構築しないでください
// 常にホワイトリストされた URI を使用
const redirectUri = ALLOWED_REDIRECT_URIS[0]; // しないこと: req.query.redirect_uri

4. トークンリーク

// トークンをログに記録しないでください
console.log('User authenticated'); // 良い
console.log(`Token: ${accessToken}`); // 絶対にしないこと

// トークンを URL に含めないでください
// 代わりに Authorization ヘッダーを使用
fetch('/api/resource', {
  headers: {
    Authorization: `Bearer ${accessToken}`,
  },
});

トークンストレージの推奨事項

ブラウザアプリケーション

// オプション 1: メモリ (最もセキュアだが、リフレッシュで失われる)
let accessToken = null;

// オプション 2: HttpOnly cookie (バックエンドが必要)
// 適切なフラグで サーバーが設定
// Secure, HttpOnly, SameSite=Strict

// オプション 3: sessionStorage (タブを閉じるとクリア)
sessionStorage.setItem('access_token', token);

// 機密トークンには localStorage を避けてください
// XSS 攻撃に脆弱

サーバーアプリケーション

// トークンを暗号化してセッションまたはデータベースに保存
const encryptedToken = encrypt(accessToken, SESSION_ENCRYPTION_KEY);
req.session.encryptedAccessToken = encryptedToken;

エラーハンドリング

const OAUTH_ERRORS = {
  invalid_request: 'リクエストが必須パラメータを失っています',
  unauthorized_client: 'クライアントは認可されていません',
  access_denied: 'ユーザーがリクエストを拒否しました',
  unsupported_response_type: 'レスポンスタイプはサポートされていません',
  invalid_scope: 'リクエストされたスコープは無効です',
  server_error: '認可サーバーがエラーに遭遇しました',
  temporarily_unavailable: 'サーバーは一時的に利用できません',
};

function handleOAuthError(error, errorDescription) {
  const message = OAUTH_ERRORS[error] || 'Unknown error';
  console.error(`OAuth Error: ${message}. Details: ${errorDescription}`);
  // ユーザーフレンドリーなエラーメッセージを表示
}

テストチェックリスト

  • PKCE フローが正しく機能する
  • State パラメータが検証される
  • 無効な state が拒否される
  • トークン有効期限が処理される
  • Refresh token ローテーションが機能する
  • 無効なトークンが拒否される
  • スコープが適切に強制される
  • Redirect URI が検証される
  • エラーケースが適切に処理される

ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
mindrally
リポジトリ
mindrally/skills
ライセンス
Apache-2.0
最終更新
不明

Source: https://github.com/mindrally/skills / ライセンス: Apache-2.0

関連スキル

Anthropic Claudeセキュリティ⭐ リポ 8,981

secure-code-guardian

認証・認可の実装、ユーザー入力の保護、OWASP Top 10の脆弱性対策が必要な場合に使用します。bcrypt/argon2によるパスワードハッシング、パラメータ化ステートメントによるSQLインジェクション対策、CORS/CSPヘッダーの設定、Zodによる入力検証、JWTトークンの構築などのカスタムセキュリティ実装に対応します。認証、認可、入力検証、暗号化、OWASP Top 10対策、セッション管理、セキュリティ強化全般で活用できます。ただし、構築済みのOAuth/SSO統合や単独のセキュリティ監査が必要な場合は、より特化したスキルの検討をお勧めします。

by Jeffallan
汎用セキュリティ⭐ リポ 1,982

claude-authenticity

APIエンドポイントが本物のClaudeによって支えられているか(ラッパーやプロキシ、偽装ではないか)を、claude-verifyプロジェクトを模した9つの重み付きルールベースチェックで検証できます。また、Claudeの正体を上書きしているプロバイダーから注入されたシステムプロンプトも抽出します。完全に自己完結しており、httpx以外の追加パッケージは不要です。Claude APIキーまたはエンドポイントを検証したい場合、サードパーティのClaudeサービスが本物か確認したい場合、APIプロバイダーのClaude正当性を監査したい場合、複数モデルを並行してテストしたい場合、またはプロバイダーが注入したシステムプロンプトを特定したい場合に使用できます。

by LeoYeAI
Anthropic Claudeセキュリティ⭐ リポ 2,159

anth-security-basics

Anthropic Claude APIのセキュリティベストプラクティスを適用し、キー管理、入力値の検証、プロンプトインジェクション対策を実施します。APIキーの保護、Claudeに送信する前のユーザー入力検証、コンテンツセーフティガードレールの実装が必要な場合に活用できます。「anthropic security」「claude api key security」「secure anthropic」「prompt injection defense」といったフレーズでトリガーされます。

by jeremylongshore
汎用セキュリティ⭐ リポ 699

x-ray

x-ray.mdプレ監査レポートを生成します。概要、強化された脅威モデル(プロトコルタイプのプロファイリング、Gitの重み付け攻撃面分析、時間軸リスク分析、コンポーザビリティ依存関係マッピング)、不変条件、統合、ドキュメント品質、テスト分析、開発者・Gitの履歴をカバーしています。「x-ray」「audit readiness」「readiness report」「pre-audit report」「prep this protocol」「protocol prep」「summarize this protocol」のキーワードで実行されます。

by pashov
汎用セキュリティ⭐ リポ 677

semgrep

Semgrepスタティック分析スキャンを実行し、カスタム検出ルールを作成します。Semgrepでのコードスキャン、セキュリティ脆弱性の検出、カスタムYAMLルールの作成、または特定のバグパターンの検出が必要な場合に使用します。重要:ユーザーが「バグをスキャンしたい」「コード品質を確認したい」「脆弱性を見つけたい」「スタティック分析」「セキュリティlint」「コード監査」または「コーディング標準を適用したい」と尋ねた場合も、Semgrepという名称を明記していなくても、このスキルを使用してください。Semgrepは30以上の言語に対応したパターンベースのコードスキャンに最適なツールです。

by wimpysworld
汎用セキュリティ⭐ リポ 591

ghost-bits-cast-attack

Java「ゴーストビッツ」/キャストアタック プレイブック(Black Hat Asia 2026)。16ビット文字が8ビットバイトに暗黙的に縮小されるJavaサービスへの攻撃時に使用します。WAF/IDSを回避して、SQLインジェクション、デシリアライゼーション型RCE、ファイルアップロード(Webシェル)、パストトラバーサル、CRLF インジェクション、リクエストスマグリング、SMTPインジェクションを実行できます。Tomcat、Spring、Jetty、Undertow、Vert.x、Jackson、Fastjson、Apache Commons BCEL、Apache HttpClient、Angus Mail、JDK HttpServer、Lettuce、Jodd、XMLWriterに影響し、WAFバイパスにより多くの「パッチ済み」CVEを再度有効化します。

by yaklang
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: mindrally · mindrally/skills · ライセンス: Apache-2.0