Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.
日本語の概要は準備中です。原文の説明を表示しています。
OAuth 2.1 compliant authentication flows (MANDATORY Q2 2026). PKCE required for ALL clients, Implicit Flow removed, modern token security.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
response_type=token; tokens returned in URL fragments leak via browser history, referrer headers, and server logs. Migrate immediately to Authorization Code + PKCE.| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
Storing tokens in localStorage | Exposed to XSS; any script on the page (including third-party) can read and exfiltrate | Use HttpOnly cookies set server-side after token exchange |
Using Implicit Flow (response_type=token) | Tokens in URL fragments leak via browser history, Referer headers, and proxy/CDN logs | Use Authorization Code Flow with PKCE |
| Collecting user passwords directly (Resource Owner Password Credentials) | Violates OAuth separation of concerns; client handles credentials it should never see | Use Authorization Code Flow; direct users to the authorization server login page |
| Wildcard or partial redirect URI matching | Open redirect attack; adversary registers https://evil.com which prefix-matches a wildcard | Register exact URIs; server rejects any URI not in the pre-approved list |
| Long-lived access tokens (>15 min) without rotation | Token theft window is unbounded; compromised token grants long-term access | Keep access tokens ≤15 min; implement refresh token rotation with reuse detection |
Step 1: Generate PKCE Challenge
// Client-side: Generate code_verifier (43-128 chars, URL-safe)
async function generatePKCE() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
const verifier = base64UrlEncode(array);
// Hash verifier to create challenge
const encoder = new TextEncoder();
const hash = await crypto.subtle.digest('SHA-256', encoder.encode(verifier));
const challenge = base64UrlEncode(new Uint8Array(hash));
return { verifier, challenge };
}
Step 2: Authorization Request
const { verifier, challenge } = await generatePKCE();
sessionStorage.setItem('pkce_verifier', verifier); // Temporary storage only
const authUrl = new URL(authorizationEndpoint);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('client_id', clientId);
authUrl.searchParams.set('redirect_uri', redirectUri); // MUST match exactly
authUrl.searchParams.set('code_challenge', challenge);
authUrl.searchParams.set('code_challenge_method', 'S256'); // SHA-256 required
authUrl.searchParams.set('scope', 'openid profile email');
authUrl.searchParams.set('state', cryptoRandomState); // CSRF protection
window.location.href = authUrl.toString();
Step 3: Token Exchange with Code Verifier
const response = await fetch(tokenEndpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
code_verifier: sessionStorage.getItem('pkce_verifier'), // Prove possession
client_id: clientId,
redirect_uri: redirectUri, // MUST match authorization request
}),
});
// Clear verifier immediately after use
sessionStorage.removeItem('pkce_verifier');
Token Lifetimes (RFC 8725)
Token Storage (CRITICAL)
// ✅ CORRECT: HttpOnly, Secure, SameSite cookies
// Server sets cookies after token exchange
res.cookie('access_token', accessToken, {
httpOnly: true, // Prevents XSS access
secure: true, // HTTPS only
sameSite: 'strict', // CSRF protection
maxAge: 15 * 60 * 1000, // 15 minutes
});
res.cookie('refresh_token', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/auth/refresh', // Limit scope
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days, rotate frequently
});
// ❌ WRONG: NEVER store tokens in localStorage or sessionStorage
localStorage.setItem('token', accessToken); // VULNERABLE TO XSS
sessionStorage.setItem('token', accessToken); // VULNERABLE TO XSS
Refresh Token Rotation
// Server-side: Rotate refresh tokens on every use
async function refreshTokens(oldRefreshToken) {
// Validate old token
const userId = await validateRefreshToken(oldRefreshToken);
// Detect token reuse (possible theft)
if (await isTokenAlreadyUsed(oldRefreshToken)) {
await revokeAllTokensForUser(userId); // Kill all sessions
throw new Error('Token reuse detected - all sessions revoked');
}
// Mark old token as used BEFORE issuing new one
await markTokenAsUsed(oldRefreshToken);
// Issue new tokens
const newAccessToken = generateAccessToken(userId, '15m');
const newRefreshToken = generateRefreshToken(userId);
return { newAccessToken, newRefreshToken };
}
❌ Implicit Flow (REMOVED in OAuth 2.1)
// NEVER DO THIS - Implicit Flow is REMOVED
authUrl.searchParams.set('response_type', 'token'); // ❌ FORBIDDEN
// Tokens in URL fragments leak via browser history, referrer headers, logs
Migration Path: Use Authorization Code Flow + PKCE instead.
❌ Resource Owner Password Credentials (REMOVED)
// NEVER DO THIS - Collecting passwords directly violates OAuth
fetch(tokenEndpoint, {
body: new URLSearchParams({
grant_type: 'password', // ❌ FORBIDDEN
username: user.email,
password: user.password,
}),
});
Migration Path: Use Authorization Code Flow for user auth, Client Credentials for service accounts.
Passkeys/WebAuthn (Recommended for 2026+)
// Register passkey
const credential = await navigator.credentials.create({
publicKey: {
challenge: serverChallenge,
rp: { name: 'Your App' },
user: {
id: userIdBytes,
name: user.email,
displayName: user.name,
},
pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
authenticatorSelection: {
authenticatorAttachment: 'platform', // Device-bound
userVerification: 'required',
},
},
});
// Authenticate with passkey
const assertion = await navigator.credentials.get({
publicKey: {
challenge: serverChallenge,
rpId: 'yourapp.com',
userVerification: 'required',
},
});
Before deploying:
Login with OAuth 2.1 (email/password)
// Use Authorization Code Flow with PKCE even for first-party login
async function login(email: string, password: string) {
// 1. Start PKCE flow
const { verifier, challenge } = await generatePKCE();
sessionStorage.setItem('pkce_verifier', verifier);
// 2. POST credentials to your auth server's login endpoint
const response = await fetch('/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password, code_challenge: challenge }),
});
// 3. Server validates credentials, returns authorization code
const { code } = await response.json();
// 4. Exchange code for tokens with verifier
await exchangeCodeForTokens(code);
}
Login with GitHub OAuth
async function loginWithGitHub() {
const { verifier, challenge } = await generatePKCE();
sessionStorage.setItem('pkce_verifier', verifier);
const authUrl = new URL('https://github.com/login/oauth/authorize');
authUrl.searchParams.set('client_id', GITHUB_CLIENT_ID);
authUrl.searchParams.set('redirect_uri', 'https://yourapp.com/auth/callback');
authUrl.searchParams.set('scope', 'user:email');
authUrl.searchParams.set('state', generateState());
// Note: GitHub doesn't support PKCE yet, but use it when available
window.location.href = authUrl.toString();
}
Logout
async function logout() {
// 1. Clear client-side cookies
document.cookie = 'access_token=; Max-Age=0; path=/';
document.cookie = 'refresh_token=; Max-Age=0; path=/';
// 2. Revoke tokens on server
await fetch('/auth/logout', { method: 'POST' });
// 3. Redirect to login
window.location.href = '/login';
}
</instructions>
<examples>
Example usage:
```
User: "Review this code for authentication flow rules compliance"
Agent: [Analyzes code against guidelines and provides specific feedback]
```
</examples>
Before starting:
cat .claude/context/memory/learnings.md
After completing: Record any new patterns or exceptions discovered.
ASSUME INTERRUPTION: Your context may reset. If it's not in memory, it didn't happen.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Ensure accessibility in UI components including semantic HTML, ARIA attributes, keyboard navigation, and WCAG 2.2 AA compliance.
日本語の概要は準備中です。原文の説明を表示しています。
Use when you want to improve response quality through meta-cognitive reasoning. Applies 15+ reasoning methods to reconsider and refine initial outputs.
日本語の概要は準備中です。原文の説明を表示しています。
N-round opposing-stance debates for trade-off analysis. Assigns pro/con roles to agents, runs structured debate rounds with quality scoring, and produces a moderator synthesis with confidence-rated recommendation. Generalizable to architecture, technology, security, and design decisions.
日本語の概要は準備中です。原文の説明を表示しています。
Force adversarial code review stance that eliminates confirmation bias — reviewer must find issues or re-analyze
日本語の概要は準備中です。原文の説明を表示しています。
Creates specialized AI agents on-demand when no existing agent matches a request. Use when the Router cannot find a suitable agent for a task. Enables self-evolution by generating persistent agents.
日本語の概要は準備中です。原文の説明を表示しています。
LLM-as-judge evaluation framework with 5-dimension rubric (accuracy, groundedness, coherence, completeness, helpfulness) for scoring AI-generated content quality with weighted composite scores and evidence citations
日本語の概要は準備中です。原文の説明を表示しています。