com um clique
auth
인증/인가 설계를 위한 가이드를 실행합니다.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
인증/인가 설계를 위한 가이드를 실행합니다.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
Interactive requirements discovery through Socratic dialogue and systematic exploration
사용자 계획을 기존 도메인 모델에 대해 stress-test하는 인터뷰 세션. 용어를 날카롭게 다듬고, 결정이 굳어질 때마다 CONTEXT.md(도메인 어휘 사전)와 ADR을 인라인으로 갱신한다. 새 기능 요구사항 탐색은 `/brainstorm`을, 기존 도메인 모델·용어와의 정합성 점검은 이 스킬을 사용한다.
Evaluate design from a UX perspective, assessing visual hierarchy, information architecture, emotional resonance, cognitive load, and overall quality with quantitative scoring, persona-based testing, automated anti-pattern detection, and actionable feedback. Use when the user asks to review, critique, evaluate, or give feedback on a design or component.
Run technical quality checks across accessibility, performance, theming, responsive design, and anti-patterns. Generates a scored report with P0-P3 severity ratings and actionable plan. Use when the user wants an accessibility check, performance audit, or technical quality review. (Impeccable design audit — distinct from /audit which validates project rules.)
Create distinctive, production-grade frontend interfaces with high design quality. Generates creative, polished code that avoids generic AI aesthetics. Use when the user asks to build web components, pages, artifacts, posters, or applications, or when any design skill requires project context. Call with 'craft' for shape-then-build, 'teach' for design context setup, or 'extract' to pull reusable components and tokens into the design system.
Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks
| name | auth |
| description | 인증/인가 설계를 위한 가이드를 실행합니다. |
| user-invocable | true |
인증/인가 설계를 위한 가이드를 실행합니다.
인증 (Authentication): "누구인가?" - 신원 확인
인가 (Authorization): "무엇을 할 수 있나?" - 권한 확인
| 방식 | 장점 | 단점 | 적합한 경우 |
|---|---|---|---|
| Session | 간단, 서버 제어 | 스케일링 어려움 | 전통적 웹앱 |
| JWT | Stateless, 확장성 | 토큰 무효화 어려움 | MSA, API |
| Passkey | 최고 보안, UX | 브라우저 지원 | 현대적 앱 |
| OAuth 2.0 | 소셜 로그인 | 복잡성 | 서드파티 연동 |
Passkey = FIDO2 + WebAuthn
- 비밀번호 없는 인증
- 생체인식/PIN 사용
- 피싱 방지 내장
- 크로스 디바이스 동기화
// 서버: 챌린지 생성
const options = await generateRegistrationOptions({
rpName: 'My App',
rpID: 'example.com',
userID: user.id,
userName: user.email,
attestationType: 'none',
authenticatorSelection: {
residentKey: 'preferred',
userVerification: 'preferred',
},
});
// 클라이언트: Passkey 생성
const credential = await navigator.credentials.create({
publicKey: options
});
// 서버: 검증 및 저장
const verification = await verifyRegistrationResponse({
response: credential,
expectedChallenge: options.challenge,
expectedOrigin: 'https://example.com',
expectedRPID: 'example.com',
});
// 서버: 인증 옵션 생성
const options = await generateAuthenticationOptions({
rpID: 'example.com',
allowCredentials: user.credentials.map(c => ({
id: c.credentialID,
type: 'public-key',
})),
});
// 클라이언트: Passkey 사용
const credential = await navigator.credentials.get({
publicKey: options
});
// 서버: 검증
const verification = await verifyAuthenticationResponse({
response: credential,
expectedChallenge: options.challenge,
expectedOrigin: 'https://example.com',
expectedRPID: 'example.com',
authenticator: storedCredential,
});
# Node.js
npm install @simplewebauthn/server @simplewebauthn/browser
# Python
pip install py-webauthn
// 토큰 생성
function generateTokens(user) {
const accessToken = jwt.sign(
{ sub: user.id, type: 'access' },
process.env.JWT_ACCESS_SECRET,
{ expiresIn: '15m', algorithm: 'RS256' }
);
const refreshToken = jwt.sign(
{ sub: user.id, type: 'refresh', jti: crypto.randomUUID() },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: '7d', algorithm: 'RS256' }
);
return { accessToken, refreshToken };
}
// Refresh Token Rotation
async function refreshAccessToken(refreshToken) {
const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
// 토큰 재사용 감지
const storedToken = await getStoredRefreshToken(decoded.jti);
if (storedToken.used) {
// 토큰 탈취 의심 - 모든 세션 무효화
await revokeAllUserSessions(decoded.sub);
throw new Error('Token reuse detected');
}
// 기존 토큰 사용 처리
await markTokenAsUsed(decoded.jti);
// 새 토큰 발급
return generateTokens({ id: decoded.sub });
}
// ✅ 권장: httpOnly Cookie + CSRF 토큰
res.cookie('accessToken', accessToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 15 * 60 * 1000,
path: '/',
});
// Refresh Token은 별도 경로
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000,
path: '/api/auth/refresh', // 특정 경로만
});
// 1. PKCE 생성
const codeVerifier = crypto.randomBytes(32).toString('base64url');
const codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest('base64url');
// 2. 인증 URL 생성
const authUrl = new URL('https://provider.com/authorize');
authUrl.searchParams.set('client_id', CLIENT_ID);
authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'openid profile email');
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');
authUrl.searchParams.set('state', crypto.randomUUID());
// 3. 토큰 교환
const tokenResponse = await fetch('https://provider.com/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: REDIRECT_URI,
client_id: CLIENT_ID,
code_verifier: codeVerifier,
}),
});
// NextAuth.js / Auth.js
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import GitHub from 'next-auth/providers/github';
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
GitHub({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
],
callbacks: {
async jwt({ token, user, account }) {
if (account) {
token.accessToken = account.access_token;
}
return token;
},
},
});
type Role = 'admin' | 'editor' | 'viewer';
type Permission = 'read' | 'write' | 'delete' | 'manage';
const rolePermissions: Record<Role, Permission[]> = {
admin: ['read', 'write', 'delete', 'manage'],
editor: ['read', 'write'],
viewer: ['read'],
};
function authorize(...requiredPermissions: Permission[]) {
return (req, res, next) => {
const userPermissions = rolePermissions[req.user.role];
const hasAll = requiredPermissions.every(p =>
userPermissions.includes(p)
);
if (!hasAll) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
}
// 사용
app.delete('/posts/:id', authorize('delete'), deletePost);
interface Policy {
resource: string;
action: string;
condition: (user: User, resource: Resource) => boolean;
}
const policies: Policy[] = [
{
resource: 'document',
action: 'edit',
condition: (user, doc) =>
doc.ownerId === user.id ||
user.role === 'admin' ||
doc.collaborators.includes(user.id),
},
{
resource: 'document',
action: 'delete',
condition: (user, doc) =>
doc.ownerId === user.id || user.role === 'admin',
},
];
function checkAccess(user: User, action: string, resource: Resource): boolean {
return policies.some(p =>
p.resource === resource.type &&
p.action === action &&
p.condition(user, resource)
);
}
## Auth Design
### Strategy
[선택한 인증 방식: Passkey / JWT / Session]
[선택 이유]
### Flow
[인증 흐름 다이어그램]
### Implementation
```typescript
// 핵심 인증 코드
| 위협 | 대책 |
|---|---|
| 피싱 | Passkey (origin binding) |
| CSRF | SameSite=Strict + CSRF token |
| XSS | httpOnly cookie |
| 브루트포스 | Rate limiting + lockout |
[RBAC/ABAC 설계]
---
요청에 맞는 인증/인가 시스템을 설계하세요.