auth-security-reviewer
Reviews authentication and authorization implementation for session management, CSRF, cookie security, and auth flow vulnerabilities with findings, severity assessment, and fix recommendations. Use for "auth review", "session security", "CSRF protection", or "authentication audit".
What this skill does
# Auth Security Reviewer
Comprehensive security review of authentication systems.
## Session Security Checklist
```typescript
// ❌ INSECURE Session Configuration
app.use(
session({
secret: "weak-secret", // Too simple
resave: true, // Unnecessary
saveUninitialized: true, // Creates unnecessary sessions
cookie: {
secure: false, // Not HTTPS-only
httpOnly: false, // Accessible via JavaScript
sameSite: false, // CSRF vulnerable
maxAge: 365 * 24 * 60 * 60 * 1000, // 1 year - too long
},
})
);
// ✅ SECURE Session Configuration
app.use(
session({
secret: process.env.SESSION_SECRET, // From environment
resave: false,
saveUninitialized: false,
name: "sessionId", // Don't use default 'connect.sid'
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JavaScript access
sameSite: "strict", // CSRF protection
maxAge: 24 * 60 * 60 * 1000, // 24 hours
domain: process.env.COOKIE_DOMAIN,
},
store: new RedisStore({
client: redisClient,
ttl: 86400,
}),
})
);
```
## JWT Security Review
```typescript
// ❌ INSECURE JWT Implementation
const token = jwt.sign(
{ userId: user.id },
"weak-secret", // Hardcoded secret
{ algorithm: "HS256" } // No expiration
);
// Store in localStorage
localStorage.setItem("token", token); // XSS vulnerable
// ✅ SECURE JWT Implementation
const token = jwt.sign(
{
userId: user.id,
role: user.role,
iat: Math.floor(Date.now() / 1000),
},
process.env.JWT_SECRET, // Strong secret from env
{
algorithm: "HS256",
expiresIn: "15m", // Short-lived
issuer: "myapp.com",
audience: "myapp.com",
}
);
// Store in httpOnly cookie
res.cookie("accessToken", token, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 15 * 60 * 1000,
});
// Refresh token with longer expiry
const refreshToken = jwt.sign(
{ userId: user.id, type: "refresh" },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: "7d" }
);
// Store refresh token in database
await storeRefreshToken(user.id, refreshToken);
```
## CSRF Protection
```typescript
// Using csurf middleware
import csrf from "csurf";
const csrfProtection = csrf({ cookie: true });
// Apply to state-changing routes
app.post("/api/transfer", csrfProtection, async (req, res) => {
// Protected from CSRF
await processTransfer(req.body);
res.json({ success: true });
});
// Provide CSRF token to frontend
app.get("/api/csrf-token", csrfProtection, (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
// Frontend usage
const csrfToken = await fetch("/api/csrf-token").then((r) => r.json());
await fetch("/api/transfer", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken.csrfToken,
},
body: JSON.stringify({ amount: 100 }),
});
```
## Password Security
```typescript
// ❌ INSECURE Password Handling
const password = req.body.password;
const hash = crypto.createHash("md5").update(password).digest("hex"); // MD5 is broken
await db.user.create({ password: hash });
// ✅ SECURE Password Handling
import bcrypt from "bcrypt";
// Hashing
const saltRounds = 12; // Adjust based on security requirements
const hash = await bcrypt.hash(password, saltRounds);
await db.user.create({ passwordHash: hash });
// Verification
const isValid = await bcrypt.compare(password, user.passwordHash);
// Password requirements
function validatePassword(password: string): boolean {
return (
password.length >= 12 &&
/[A-Z]/.test(password) && // Uppercase
/[a-z]/.test(password) && // Lowercase
/[0-9]/.test(password) && // Number
/[^A-Za-z0-9]/.test(password) // Special char
);
}
// Check against breached passwords
import { pwnedPassword } from "hibp";
const breachCount = await pwnedPassword(password);
if (breachCount > 0) {
throw new Error("This password has been found in data breaches");
}
```
## Multi-Factor Authentication
```typescript
// TOTP-based MFA
import speakeasy from "speakeasy";
import qrcode from "qrcode";
// Generate secret
const secret = speakeasy.generateSecret({
name: `MyApp (${user.email})`,
issuer: "MyApp",
});
// Store secret
await db.user.update({
where: { id: user.id },
data: {
mfaSecret: secret.base32,
mfaEnabled: false, // Not enabled until verified
},
});
// Generate QR code
const qrCodeUrl = await qrcode.toDataURL(secret.otpauth_url);
// Verify TOTP token
function verifyMFA(token: string, secret: string): boolean {
return speakeasy.totp.verify({
secret,
encoding: "base32",
token,
window: 2, // Allow 2 time steps before/after
});
}
// Backup codes
function generateBackupCodes(): string[] {
return Array.from({ length: 10 }, () =>
crypto.randomBytes(4).toString("hex").toUpperCase()
);
}
```
## Authorization Vulnerabilities
```typescript
// ❌ INSECURE: Missing authorization check
app.get("/api/users/:id/profile", async (req, res) => {
const profile = await db.user.findUnique({
where: { id: req.params.id },
});
res.json(profile); // Anyone can access any profile!
});
// ✅ SECURE: Proper authorization
app.get("/api/users/:id/profile", authenticate, async (req, res) => {
// Check if user can access this profile
if (req.user.id !== req.params.id && req.user.role !== "ADMIN") {
return res.status(403).json({ error: "Forbidden" });
}
const profile = await db.user.findUnique({
where: { id: req.params.id },
});
res.json(profile);
});
// ❌ INSECURE: IDOR vulnerability
app.delete("/api/orders/:id", async (req, res) => {
await db.order.delete({ where: { id: req.params.id } });
res.json({ success: true });
});
// ✅ SECURE: Verify ownership
app.delete("/api/orders/:id", authenticate, async (req, res) => {
const order = await db.order.findUnique({
where: { id: req.params.id },
});
if (!order) {
return res.status(404).json({ error: "Not found" });
}
if (order.userId !== req.user.id) {
return res.status(403).json({ error: "Forbidden" });
}
await db.order.delete({ where: { id: req.params.id } });
res.json({ success: true });
});
```
## Session Fixation Prevention
```typescript
// ❌ INSECURE: Session not regenerated on login
app.post("/login", async (req, res) => {
const user = await authenticate(req.body);
req.session.userId = user.id;
res.json({ success: true });
});
// ✅ SECURE: Regenerate session on login
app.post("/login", async (req, res) => {
const user = await authenticate(req.body);
// Regenerate session to prevent fixation
req.session.regenerate((err) => {
if (err) return res.status(500).json({ error: "Server error" });
req.session.userId = user.id;
res.json({ success: true });
});
});
// Also regenerate on privilege escalation
app.post("/admin/elevate", async (req, res) => {
// Verify admin credentials
await verifyAdminPassword(req.body.password);
// Regenerate session
req.session.regenerate((err) => {
if (err) return res.status(500).json({ error: "Server error" });
req.session.isAdmin = true;
res.json({ success: true });
});
});
```
## Rate Limiting on Auth Endpoints
```typescript
import rateLimit from "express-rate-limit";
// Strict rate limit for login
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts
message: "Too many login attempts, please try again later",
standardHeaders: true,
legacyHeaders: false,
// Use IP + username for more granular limiting
keyGenerator: (req) => `${req.ip}-${req.body.email}`,
});
app.post("/api/login", loginLimiter, async (req, res) => {
// Login logic
});
// Even stricter for password reset
const resetLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 3,
message: "Too many password reset attempts",
});
app.post("/api/password-reset", resetLimiter, async (req, res) => {
// Password reset logic
});
```
## Security Testing
```typescript
// tests/auth-securitRelated in Security
mac-ops
IncludedComprehensive macOS workstation operations — diagnose kernel panics, identify failing drives, audit launchd startup items, decode wake reasons, triage TCC permission denials, manage APFS snapshots, recover from no-boot. Use for: Mac is slow, slow bootup, won't boot, kernel panic, kernel_task hot, mds_stores CPU, photoanalysisd, cloudd, login loop, gray screen, sleep wake failure, drive failing, IO errors, APFS snapshots eating space, Time Machine local snapshots, Spotlight indexing, launchd, LaunchAgent, LaunchDaemon, login items, TCC permissions, Full Disk Access, Screen Recording denied, Gatekeeper, quarantine, com.apple.quarantine, app is damaged, helper tool, /Library/PrivilegedHelperTools, pmset, wake reasons, dark wake, sysdiagnose, panic.ips, DiagnosticReports, configuration profile, MDM profile, remote diagnostics over SSH.
a11y-audit
IncludedRun accessibility audits on web projects combining automated scanning (axe-core, Lighthouse) with WCAG 2.1 AA compliance mapping, manual check guidance, and structured reporting. Output is configurable: markdown report only, markdown plus machine-readable JSON, or markdown plus issue tracker integration. Use this skill whenever the user mentions "accessibility audit", "a11y audit", "WCAG audit", "accessibility check", "compliance scan", or asks to check a web project for accessibility issues. Also trigger when the user wants to verify WCAG conformance or map findings to a specific standard (CAN-ASC-6.2, EN 301 549, ADA/AODA).
erpclaw
IncludedAI-native ERP system with self-extending OS. Full accounting, invoicing, inventory, purchasing, tax, billing, HR, payroll, advanced accounting (ASC 606/842, intercompany, consolidation), and financial reporting. 413 actions across 14 domains, 43 expansion modules. Constitutional guardrails, adversarial audit, schema migration. Double-entry GL, immutable audit trail, US GAAP.
assess
IncludedAssesses and rates quality 0-10 across multiple dimensions (correctness, maintainability, security, performance, testability, simplicity) with pros/cons analysis. Compares against project conventions and prior decisions from memory. Produces structured evaluation reports with actionable improvement suggestions. Use when evaluating code, designs, architectures, or comparing alternative approaches.
spring-boot-security-jwt
IncludedProvides JWT authentication and authorization patterns for Spring Boot 3.5.x covering token generation with JJWT, Bearer/cookie authentication, database/OAuth2 integration, and RBAC/permission-based access control using Spring Security 6.x. Use when implementing authentication or authorization in Spring Boot applications.
code-hardcode-audit
IncludedDetect hardcoded values, magic numbers, and leaked secrets. TRIGGERS - hardcode audit, magic numbers, PLR2004, secret scanning.