auth-ops について
auth-opsは、複数の言語やフレームワークで認証・認可を設計する開発者向けのリファレンススキルです。判断ツリー、クイックリファレンス、安全性チェックリスト、分野別資料で構成されています。
主な機能
- 01認証方式の判断ツリー
- 02JWTとOAuth2のガイダンス
- 03認可モデルのリファレンス
- 04セッションとCookieの安全対策
- 05パスワードとMFAのチェックリスト
- 06アイデンティティプロキシの安全対策
活用シーン
- 01アプリの認証フローの選定
- 02JWTクレームとトークン処理の確認
- 03ロール・権限・ポリシーモデルの計画
- 04セッション・パスワード・MFA運用の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ 0xdarkmatter/ claude-mods --skill auth-opsインストール後、Claude Code で/auth-opsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/.gitkeepreferences/authorization.mdbetter-auth.mdcloudflare-access.mdimplementation.mdjwt-sessions.mdoauth2-oidc.mdscripts/.gitkeep詳細
認証オペレーション
言語やフレームワークを問わず、安全なアプリケーション開発に役立つ、包括的な認証・認可のパターンです。
認証方式の選択ツリー
このツリーを使って、ユースケースに適した認証戦略を選択してください。
What are you building?
│
├─ Traditional web application (server-rendered)?
│ └─ Session-based authentication
│ ├─ Server stores session data (Redis/DB)
│ ├─ Session ID in httpOnly cookie
│ └─ Best for: monoliths, SSR apps, admin panels
│
├─ API consumed by multiple clients?
│ └─ JWT (JSON Web Tokens)
│ ├─ Stateless, self-contained tokens
│ ├─ Access token (short-lived) + refresh token (long-lived)
│ └─ Best for: microservices, mobile apps, SPAs via BFF
│
├─ Service-to-service communication?
│ └─ API keys or Client Credentials (OAuth2)
│ ├─ API keys: simple, scoped, rotatable
│ ├─ Client Credentials: OAuth2 standard, token-based
│ └─ Best for: internal services, third-party integrations
│
├─ Third-party login (Google, GitHub, etc.)?
│ └─ OAuth2 / OpenID Connect
│ ├─ Authorization Code + PKCE for web/mobile
│ ├─ Delegate identity to trusted providers
│ └─ Best for: consumer apps, social login
│
├─ Passwordless authentication?
│ └─ Passkeys (WebAuthn) or Magic Links
│ ├─ Passkeys: phishing-resistant, biometric/hardware
│ ├─ Magic links: email-based, time-limited
│ └─ Best for: high-security, modern UX
│
└─ Internal tool / staff app with an existing IdP?
└─ Identity-aware proxy (Cloudflare Access)
├─ Authn enforced at the edge, before your origin
├─ Origin verifies the proxy's signed JWT (never a bare header)
└─ Best for: admin panels, partner portals, not consumer signup
JWT クイックリファレンス
構造
Header.Payload.Signature
Header: { "alg": "RS256", "typ": "JWT" }
Payload: { "iss": "auth.example.com", "sub": "user_123", ... }
Signature: RSASHA256(base64(header) + "." + base64(payload), privateKey)
一般的なクレーム
| クレーム | 名前 | 目的 | 例 |
|---|---|---|---|
iss | 発行者 | トークンの発行元 | "auth.example.com" |
sub | サブジェクト | トークンが表す対象 | "user_123" |
exp | 有効期限 | トークンの有効期限 | 1700000000(Unix タイムスタンプ) |
iat | 発行日時 | トークンの作成日時 | 1699999100 |
aud | オーディエンス | 想定される受信者 | "api.example.com" |
jti | JWT ID | トークンの一意な識別子 | "a1b2c3d4"(失効用) |
nbf | 有効開始日時 | この時刻より前はトークンが無効 | 1699999100 |
署名アルゴリズム
| アルゴリズム | 種類 | 鍵 | 使用する場面 |
|---|---|---|---|
| RS256 | 非対称(RSA) | 公開鍵/秘密鍵のペア | 分散システム、複数の検証者 |
| ES256 | 非対称(ECDSA) | 公開鍵/秘密鍵のペア | RS256 と同様。鍵や署名が小さい場合 |
| HS256 | 対称(HMAC) | 共有シークレット | 単一サービス、シンプルな構成 |
目安: トークンの発行者と検証者が別々のサービスである場合は、非対称方式(RS256/ES256)を使用してください。HS256 は、単一のサービスがトークンの作成と検証の両方を行う場合にのみ使用してください。
アクセストークン+リフレッシュトークンのパターン
┌──────────┐ ┌──────────┐
│ Client │─── login ────────>│ Auth │
│ │<── access (15m) ──│ Server │
│ │<── refresh (7d) ──│ │
│ │ └──────────┘
│ │─── API call ─────>┌──────────┐
│ │ (access token) │ Resource │
│ │<── response ──────│ Server │
│ │ └──────────┘
│ │─── access expired │ │
│ │─── refresh ──────>│ Auth │
│ │<── new access ────│ Server │
│ │<── new refresh ───│ (rotate)│
└──────────┘ └──────────┘
- アクセストークン: 有効期間が短く(5~15 分)、API 呼び出しに使用します
- リフレッシュトークン: 有効期間が長く(7~30 日)、新しいアクセストークンの取得に使用します
- ローテーション: 使用ごとに新しいリフレッシュトークンを発行し、古いものを無効化します
- ファミリー検出: リフレッシュトークンの系譜を追跡します。失効済みのトークンが再利用された場合は、ファミリー全体を無効化します
OAuth2 フローの選択ツリー
What type of client?
│
├─ Web app with backend (Next.js, Rails, Django)?
│ └─ Authorization Code + PKCE
│ ├─ Redirect user to authorization server
│ ├─ Receive code at callback URL
│ ├─ Exchange code for tokens server-side
│ └─ PKCE prevents code interception attacks
│
├─ SPA (React, Vue) without backend?
│ └─ Authorization Code + PKCE (via BFF)
│ ├─ Use a Backend-for-Frontend to handle tokens
│ ├─ Never store tokens in browser-accessible storage
│ └─ BFF proxies API calls with token attached
│
├─ Mobile app (iOS, Android)?
│ └─ Authorization Code + PKCE
│ ├─ Use custom URI scheme or universal links for redirect
│ ├─ PKCE is mandatory (public client)
│ └─ Store tokens in secure enclave/keystore
│
├─ Server-to-server (no user)?
│ └─ Client Credentials
│ ├─ Authenticate with client_id + client_secret
│ ├─ No user context, service-level access
│ └─ Token cached until expiry
│
├─ CLI tool or smart TV?
│ └─ Device Code
│ ├─ Display code and URL to user
│ ├─ User authenticates on another device
│ ├─ CLI/TV polls for completion
│ └─ Good UX for input-constrained devices
│
└─ Microservice acting on behalf of a user?
└─ Token Exchange (RFC 8693)
├─ Exchange user's token for a scoped downstream token
├─ Maintains user context across services
└─ Use `act` claim for delegation chain
認可モデルの選択ツリー
How complex are your access control needs?
│
├─ Simple: just "can user X do action Y"?
│ └─ Permission-based (direct)
│ ├─ user_permissions table
│ ├─ Simple to implement, hard to scale
│ └─ Good for: small apps, prototypes
│
├─ Users grouped into roles with fixed permissions?
│ └─ RBAC (Role-Based Access Control)
│ ├─ Roles: admin, editor, viewer
│ ├─ Each role has a set of permissions
│ ├─ Users assigned one or more roles
│ └─ Good for: most apps, admin panels, team tools
│
├─ Decisions depend on attributes (time, location, resource owner)?
│ └─ ABAC (Attribute-Based Access Control)
│ ├─ Policies evaluate subject + resource + environment attributes
│ ├─ "Allow if user.department == resource.department AND time < 17:00"
│ ├─ Flexible but complex
│ └─ Good for: enterprise, compliance-heavy, context-dependent access
│
└─ Access based on relationships (owner, parent, shared with)?
└─ ReBAC (Relationship-Based Access Control)
├─ Google Zanzibar model
├─ Tuples: user:alice#viewer@document:report
├─ Supports inheritance: folder viewer → document viewer
├─ Tools: OpenFGA, SpiceDB, Ory Keto
└─ Good for: file sharing, nested resources, social features
セッション管理クイックリファレンス
Cookie のセキュリティ設定
| 設定 | 値 | 目的 |
|---|---|---|
SameSite | Strict | 同一サイトのリクエストにのみ Cookie を送信します(CSRF 対策として最適) |
SameSite | Lax | トップレベルのナビゲーションで Cookie を送信します(適切なデフォルト) |
SameSite | None | クロスサイトのリクエストでも Cookie を送信します(Secure が必要) |
Secure | true | HTTPS 経由でのみ Cookie を送信します |
HttpOnly | true | JavaScript から Cookie にアクセスできないようにします(XSS による窃取を防止) |
__Host- prefix | N/A | Secure が必須で、Domain を指定せず、Path=/ にする必要があります(最も厳格) |
__Secure- prefix | N/A | Secure フラグが必須です |
Max-Age | 秒 | Cookie の有効期間です(Expires よりこちらを推奨) |
Path | / | Cookie の適用範囲をパスに限定します(通常は /) |
推奨される Cookie 設定
Set-Cookie: __Host-session=abc123;
Secure;
HttpOnly;
SameSite=Lax;
Max-Age=86400;
Path=/
セッション有効期限の戦略
| 戦略 | 一般的な値 | 備考 |
|---|---|---|
| アイドルタイムアウト | 15~30 分 | リクエストごとにリセットします |
| 絶対タイムアウト | 8~24 時間 | 再認証を強制します |
| スライディングウィンドウ | アイドル時 30 分、最大 8 時間 | バランスに優れています |
| ログイン状態を保持 | 30 日 | セッションを延長し、権限を制限します |
パスワード処理クイックリファレンス
ハッシュ化アルゴリズム
| アルゴリズム | 評価 | 備考 |
|---|---|---|
| argon2id | 最適 | メモリハードで GPU 攻撃に強く、OWASP が推奨 |
| bcrypt | 優良 | 実績があり、コスト係数は 12 以上、入力上限は 72 バイト |
| scrypt | 優良 | メモリハードですが、ライブラリのサポートは比較的少ない |
| PBKDF2 | 許容可能 | FIPS 準拠。SHA-256 を使い、反復回数は 60 万回以上にしてください |
| SHA-256/512 | 不適切 | 処理が速すぎ、ソルトが組み込まれておらず、総当たり攻撃を受けやすい |
| MD5 | 使用禁止 | 破られており、レインボーテーブルが広く出回っています |
パスワードのルール(NIST 800-63B)
| ルール | ガイダンス |
|---|---|
| 最小文字数 | 8 文字(12 文字以上を推奨) |
| 最大文字数 | 少なくとも 64 文字 |
| 複雑さのルール | 特殊文字/大文字/数字を必須にしないでください |
| 漏えい済みパスワードの確認 | 既知の漏えい済みパスワードと照合します(HaveIBeenPwned API) |
| パスワードのヒント | 許可しないでください |
| 強制的な定期変更 | 定期的な変更を強制しないでください(漏えい時のみ) |
| パスワード欄への貼り付け | 許可してください(パスワードマネージャーに対応) |
ログイン試行のレート制限
| 試行回数 | 応答 |
|---|---|
| 1-5 | 通常のログイン |
| 6-10 | CAPTCHA を必須にする |
| 11-20 | 段階的に遅延を設ける(2s、4s、8s...) |
| 20+ | 一時的にアカウントをロックする(15-30 分) |
重要: タイミングを利用したユーザー名の列挙を防ぐため、成功時と失敗時の応答時間を一定にしてください。
MFA クイックリファレンス
セキュリティ別の方式
| 方式 | セキュリティ | UX | 備考 |
|---|---|---|---|
| WebAuthn/Passkeys | 最高 | 良好 | フィッシング耐性があり、ハードウェアで保護されます |
| TOTP(認証アプリ) | 高 | 普通 | アプリベース(Google/Microsoft Authenticator) |
| プッシュ通知 | 高 | 良好 | モバイルアプリが必要です |
| メール OTP | 中 | 普通 | メールのセキュリティに依存します |
| SMS OTP | 低 | 簡単 | SIM スワップの危険性があるため、フォールバックとしてのみ使用してください |
TOTP 実装チェックリスト
- 160 ビットのシークレットを生成する(base32 でエンコード)
- 発行者とアカウントを含む otpauth:// URI を作成する
- 認証アプリでスキャンできる QR コードを表示する
- 有効化する前に、最初のコードの検証を必須にする
- 現在の時間枠 +/- 1(30 秒間隔)を許容する
- 1 回限りのバックアップコードを 8~10 個生成する
- 保存する前にバックアップコードをハッシュ化する
- 本人確認済みの ID による復旧を許可する
パスキー/WebAuthn チェックリスト
- サーバー上で暗号学的チャレンジを生成する
- relying party ID(ドメイン)を設定する
- 認証情報の公開鍵と ID を保存する
- 認証時に署名を検証する
- ユーザーごとに複数の認証情報をサポートする
- プラットフォーム認証器とクロスプラットフォーム認証器を処理する
- フォールバック認証方式を用意する
ID 認識プロキシのクイックリファレンス
認証がプロキシエッジ(Cloudflare Access、Google IAP、oauth2-proxy)に委任されている場合、次の 2 つの不変条件がモデル全体を支えます。
- アサーションを検証します。 プロキシの ID ヘッダーは署名付き JWT です。リクエストごとに、プロキシの JWKS を使って署名 + 発行者 + アプリケーションごとの audience を検証してください。メールアドレスを示すプレーンな便宜上のヘッダーは決して信頼しないでください。
- プロキシを迂回するすべての経路を閉じます。 ヘッダーに意味があるのは、プロキシだけがオリジンに到達する手段である場合(
workers_dev = false、ファイアウォールで保護されたオリジン、またはトンネル)に限られます。オリジンが公開されていると、どのヘッダーも偽造可能になります。
Proxy edge (authn) ──JWT header──> Origin verifies JWT ──> app user lookup ──> role/scope binding
│ │ 403 on any failure │ 403 if no row (server-side)
└ IdP / OTP login, sessions └ cached JWKS, └ proxy admits ≠ app authorizes
rate limits, bot defense refetch on unknown kid
マシン向けルート(webhook、取り込み)には、エッジで Service-Auth/Bypass を適用し、オリジンでベアラーキーを使用します。これらは人間向け認証ミドルウェアの外側に配置してください。詳細については、references/cloudflare-access.md を参照してください。
よくある落とし穴
| 落とし穴 | 危険な理由 | 対策 |
|---|---|---|
| JWT を localStorage に保存する | XSS によってトークンが盗まれる可能性があり、ブラウザーによる有効期限の適用もありません | httpOnly Cookie または BFF パターンを使用します |
| OAuth2 で PKCE を使用しない | 認可コードの傍受攻撃が可能になります | 機密クライアントであっても、必ず PKCE を使用します |
| RBAC でロールが増えすぎる | 数百ものロールの管理が困難になります | 複雑なシナリオでは ABAC または ReBAC に移行します |
| トークンを文字列比較する | タイミング攻撃によって、トークンの値が1文字ずつ漏えいします | 定時間比較(crypto.timingSafeEqual)を使用します |
| トークン失効戦略がない | 侵害された JWT を有効期限前に無効化できません | 有効期限を短くしてリフレッシュトークンを使用するか、ブロックリストを管理します |
credentials: true を指定した CORS | Access-Control-Allow-Origin: * は認証情報と併用できません | オリジンを正確に指定し、Access-Control-Allow-Credentials: true を設定します |
Secure を指定せずに SameSite=None を使用する | ブラウザーが Cookie を通知なしに拒否します | SameSite=None には必ず Secure フラグを指定します |
| 検出せずにリフレッシュトークンを再利用する | 盗まれたリフレッシュトークンによって、アクセスが無期限に許可されます | リフレッシュトークンをローテーションし、再利用を検出します(トークンファミリー) |
| OAuth2 Implicit グラントを使用する | トークンが URL フラグメントに露出し、リフレッシュトークンもありません | 代わりに Authorization Code + PKCE を使用します(Implicit は非推奨です) |
| パスワードを URL またはログに含める | URL はプロキシ、ブラウザー、サーバーによってログに記録されます | 認証情報は必ずリクエストボディまたはヘッダーで送信します |
| Cookie 使用時に CSRF 対策がない | Cookie ベースの認証はクロスサイトリクエストフォージェリに対して脆弱です | 状態を変更する操作では、SameSite Cookie と CSRF トークンを使用します |
| 有効期間の長いアクセストークン(数時間〜数日) | トークンが侵害された場合の攻撃可能時間が長くなります | アクセストークンの有効期間を5〜15分にし、リフレッシュトークンを使用します |
| API キーを平文で保存する | データベースが侵害されると、すべてのキーが漏えいします | 保存するキーをハッシュ化し(キーの SHA-256)、検索用にプレフィックスを保存します |
JWT の aud クレームを検証しない | Service A 用のトークンが Service B で受け入れられます | aud がサービス識別子と一致することを必ず検証します |
| セッション固定攻撃 | 攻撃者がログイン前にセッション ID を設定し、その後セッションを乗っ取ります | 認証後にセッション ID を再生成します |
| コードにシークレットをハードコードする | ソース管理を通じてシークレットが漏えいします | 環境変数またはシークレットマネージャー(Vault、AWS SSM)を使用します |
| Identity-Aware プロキシの署名されていないメールヘッダーを信頼する | プロキシを経由しないパスでは、ヘッダーを攻撃者が設定できます | プロキシの署名済み JWT(sig + issuer + audience)を検証し、プロキシを迂回するすべての経路を閉じます |
| 認証ライブラリのミドルウェアだけでセッションを確認する | フレームワークのミドルウェアは迂回される可能性があります(Next.js CVE-2025-29927 クラス) | データアクセス層またはルートハンドラーでもセッションを再確認します |
参考ファイル
| ファイル | 内容 | 行数 |
|---|---|---|
references/jwt-sessions.md | JWT の構造、署名、セッション、Cookie、CSRF、ストレージ | 約650 |
references/oauth2-oidc.md | OAuth2 フロー、OIDC、プロバイダー連携、ソーシャルログイン | 約700 |
references/authorization.md | RBAC、ABAC、ReBAC、RLS、マルチテナント、監査ログ | 約600 |
references/implementation.md | パスワードハッシュ化、MFA、レート制限、API キー、リセットフロー | 約550 |
references/cloudflare-access.md | Cloudflare Access を介した Identity-Aware プロキシ:アプリ/ポリシーの構成、トークンクレーム、JWT 検証、オリジンを閉じる前提条件、サービス認証、セッション/ログアウト/SPA、ローカル開発 | 約330 |
references/better-auth.md | Better Auth ライブラリ:サーバー/クライアントのセットアップ、アダプター、セッションモデル、ソーシャルログイン、プラグインカタログ(パスキー/2FA/組織/SSO)、Hono 連携、移行 | 約240 |
関連項目
- security-ops - より広範なセキュリティパターン:OWASP、ヘッダー、入力検証、暗号化
- api-design-ops - 認証エンドポイントやレート制限を含む API 設計
- postgres-ops - データベース認可のための行レベルセキュリティ(RLS)ポリシー
- cloudflare-ops - Workers ランタイム、wrangler の設定、シークレット、Access の背後にあるオリジンのデプロイの仕組み
コメント
Markdown 対応