auth-patterns
Use when implementing authentication. Use when storing passwords. Use when asked to store credentials insecurely.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when implementing authentication. Use when storing passwords. Use when asked to store credentials insecurely.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | auth-patterns |
| description | Use when implementing authentication. Use when storing passwords. Use when asked to store credentials insecurely. |
Never store plain passwords. Use proven auth patterns. Security is not optional.
Authentication is the front door to your system. Get it wrong and everything else is compromised.
NEVER store passwords in plain text. ALWAYS use slow hashing.
No exceptions:
If passwords aren't properly hashed, STOP:
// ❌ VIOLATION: Plain text password
await db.users.create({
email,
password: password // Stored as-is!
});
// ❌ VIOLATION: Fast hash (crackable)
const hashed = crypto.createHash('sha256').update(password).digest('hex');
// ❌ VIOLATION: Reversible encryption
const encrypted = encrypt(password, key); // Can be decrypted!
// ✅ CORRECT: Slow, salted hashing with bcrypt
import bcrypt from 'bcrypt';
const SALT_ROUNDS = 12; // Adjust based on your hardware
async function hashPassword(plain: string): Promise<string> {
return bcrypt.hash(plain, SALT_ROUNDS);
}
async function verifyPassword(plain: string, hashed: string): Promise<boolean> {
return bcrypt.compare(plain, hashed);
}
// Registration
app.post('/register', async (req, res) => {
const { email, password } = validated(req.body);
const hashedPassword = await hashPassword(password);
await db.users.create({
email,
password: hashedPassword // Store the hash
});
res.status(201).json({ success: true });
});
// Login
app.post('/login', async (req, res) => {
const { email, password } = validated(req.body);
const user = await db.users.findByEmail(email);
// Constant-time comparison to prevent timing attacks
// Always verify even if user not found
const dummyHash = '$2b$12$dummy.hash.here';
const isValid = await verifyPassword(password, user?.password ?? dummyHash);
if (!user || !isValid) {
// Same error for both cases - prevents user enumeration
return res.status(401).json({ error: 'Invalid credentials' });
}
const token = generateToken(user);
res.json({ token });
});
Pressure: "Just store it for now, we'll add encryption"
Response: Plain text passwords get leaked. Breaches happen fast.
Action: Hash from day one. It's 3 lines of code.
Pressure: "Internal network, no one can access it"
Response: Firewalls get breached. Insiders exist. Defense in depth.
Action: Hash regardless of network security.
Pressure: "SHA256 is a strong hash"
Response: SHA256 is fast - billions per second on GPU. Bcrypt is intentionally slow.
Action: Use bcrypt or Argon2. Speed is the enemy.
Pressure: "Dev database doesn't need security"
Response: Dev code becomes prod code. Dev habits become prod habits.
Action: Use proper hashing in all environments.
password column without "hash" in namecrypto.createHash for passwords===All of these mean: Fix the auth implementation.
| Insecure | Secure |
|---|---|
| Plain text storage | bcrypt/Argon2 hash |
| SHA256(password) | bcrypt.hash(password, 12) |
=== comparison | bcrypt.compare() |
| "User not found" error | "Invalid credentials" |
| Unlimited login attempts | Rate limiting + lockout |
| Excuse | Reality |
|---|---|
| "We'll encrypt later" | Do it now. Takes 3 lines. |
| "Behind firewall" | Defense in depth required. |
| "SHA256 is secure" | Too fast. Use slow hashes. |
| "Just development" | Dev becomes prod. |
| "Internal users only" | Insiders cause breaches too. |
| "We trust our database" | Databases get dumped. |
Hash passwords with bcrypt. Use constant-time comparison. Return generic errors.
Password security is non-negotiable. Use slow hashes (bcrypt, Argon2). Prevent timing attacks. Don't leak user existence. Rate limit everything.
Use when writing tests. Use when test structure is unclear. Use when arrange/act/assert phases are mixed.
Use when designing or modifying APIs. Use when adding breaking changes. Use when clients depend on API stability.
Use when same data is fetched repeatedly. Use when database queries are slow. Use when implementing caching without invalidation strategy.
Use when tempted to use class inheritance. Use when creating class hierarchies. Use when subclass needs only some parent behavior.
Use when acquiring multiple locks. Use when operations wait for each other. Use when system hangs without crashing.
Use when a class creates its own dependencies. Use when instantiating concrete implementations inside a class. Use when told to avoid dependency injection for simplicity.