Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Secure Auth Patterns

ASecurity

Authentication and session implementation patterns: password hashing, session cookie settings, JWT validation and its pitfalls, and access control checks, with language-specific examples. Use when building or reviewing login, sessions, tokens, or authorization code.

4 stars
0 votes
0 copies
0 views
Added 10/1/2026
securityjavascriptpythongojavanodeexpressdjangorailsspringgit

Works with

cliapi

Security Analysis

A100/100

Scanned 10/1/2026

$npx -y skills add HermeticOrmus/LibreSecOps-Claude-Code --skill secure-auth-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Secure Auth Patterns?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Secure Auth Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hermeticormus-secure-auth-patterns/badge)](https://www.skillsdirectory.com/skills/hermeticormus-secure-auth-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: "secure-auth-patterns"
description: "Authentication and session implementation patterns: password hashing, session cookie settings, JWT validation and its pitfalls, and access control checks, with language-specific examples. Use when building or reviewing login, sessions, tokens, or authorization code."
---

# Secure Auth Patterns

> Authentication, session management, and access control implementation patterns with language-specific secure code examples.

## Knowledge Base

### Password Storage

Never store passwords in plaintext, encrypted form, or with weak hashes (MD5, SHA-1, unsalted SHA-256). Use adaptive hashing algorithms designed for password storage.

**Algorithm selection** (OWASP 2023 recommendations):

| Algorithm | Recommended Parameters | Notes |
|-----------|----------------------|-------|
| Argon2id | Memory: 19456 KB, Iterations: 2, Parallelism: 1 | Preferred. Memory-hard, GPU-resistant |
| bcrypt | Cost factor: 12+ | Widely supported, 72-byte input limit |
| scrypt | N: 2^17, r: 8, p: 1 | Memory-hard, less common than Argon2 |
| PBKDF2-SHA256 | 600,000 iterations | Only if above are unavailable (FIPS) |

**Implementation examples**:

```python
# Python - Argon2 (preferred)
from argon2 import PasswordHasher
ph = PasswordHasher(time_cost=2, memory_cost=19456, parallelism=1)
hash = ph.hash(password)
# Verify
try:
    ph.verify(hash, password)
    if ph.check_needs_rehash(hash):  # Upgrade params over time
        new_hash = ph.hash(password)
except VerifyMismatchError:
    # Invalid password

# Python - bcrypt
import bcrypt
hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
if bcrypt.checkpw(password.encode(), hash):
    # Valid
```

```javascript
// Node.js - bcrypt
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);
const valid = await bcrypt.compare(password, hash);

// Node.js - Argon2
const argon2 = require('argon2');
const hash = await argon2.hash(password, {
  type: argon2.argon2id,
  memoryCost: 19456,
  timeCost: 2,
  parallelism: 1
});
const valid = await argon2.verify(hash, password);
```

```go
// Go - bcrypt
import "golang.org/x/crypto/bcrypt"
hash, err := bcrypt.GenerateFromPassword([]byte(password), 12)
err = bcrypt.CompareHashAndPassword(hash, []byte(password))

// Go - Argon2
import "golang.org/x/crypto/argon2"
salt := make([]byte, 16)
rand.Read(salt)
hash := argon2.IDKey([]byte(password), salt, 2, 19456, 1, 32)
```

```java
// Java - bcrypt (jBCrypt)
String hash = BCrypt.hashpw(password, BCrypt.gensalt(12));
boolean valid = BCrypt.checkpw(password, hash);

// Java - Argon2 (argon2-jvm)
Argon2 argon2 = Argon2Factory.create(Argon2Factory.Argon2Types.ARGON2id);
String hash = argon2.hash(2, 19456, 1, password.toCharArray());
boolean valid = argon2.verify(hash, password.toCharArray());
```

### Session Management

**Session token requirements**:
- Minimum 128 bits of entropy from a CSPRNG
- Transmitted only over HTTPS
- Cookie attributes: `Secure`, `HttpOnly`, `SameSite=Strict` (or `Lax`)
- Server-side session storage (not just a signed cookie containing all session data)
- Regenerate session ID on privilege level change (login, role change)
- Absolute timeout (max session lifetime) and idle timeout

**Cookie configuration**:
```
Set-Cookie: session=<token>; Secure; HttpOnly; SameSite=Strict; Path=/; Max-Age=3600
```

**Session lifecycle**:
1. **Creation**: Generate new session ID after successful authentication. Invalidate any pre-authentication session.
2. **Validation**: Check session exists, is not expired, belongs to the authenticated user, and has not been revoked.
3. **Renewal**: Regenerate session ID on privilege changes. Maintain session data but change the identifier.
4. **Termination**: Invalidate session server-side on logout. Clear the cookie client-side. Provide "logout everywhere" capability.

### JWT Security

JWTs are frequently misimplemented. Key requirements:

**Algorithm enforcement**:
```javascript
// VULNERABLE - Accepts any algorithm
jwt.verify(token, secret);

// SECURE - Explicitly specify allowed algorithms
jwt.verify(token, secret, { algorithms: ['HS256'] });

// For RS256 (asymmetric)
jwt.verify(token, publicKey, { algorithms: ['RS256'] });
```

**Critical claims to validate**:
- `exp` (expiration) -- always set, always check
- `iss` (issuer) -- verify against expected value
- `aud` (audience) -- verify the token is intended for this service
- `iat` (issued at) -- reject tokens issued in the future
- `nbf` (not before) -- reject tokens not yet valid

**JWT pitfalls**:
- Algorithm confusion: RS256 public key used as HS256 secret
- `alg: "none"` -- some libraries accept unsigned tokens
- Storing sensitive data in payload (JWT payload is base64, not encrypted)
- No revocation mechanism without additional infrastructure (token blacklist)
- Overly long expiration times

### Multi-Factor Authentication (MFA)

**TOTP implementation requirements** (RFC 6238):
- Secret: 160+ bits, generated server-side
- Time step: 30 seconds
- Allow clock skew: +/- 1 time step
- Rate limit verification attempts (prevent brute force)
- Provide backup codes (one-time use, stored hashed)
- Validate TOTP token before enabling MFA (user proves they set up authenticator correctly)

**MFA bypass prevention**:
- Do not issue session tokens until MFA is verified
- Do not reveal whether username/password was correct before MFA
- Implement step-up authentication for sensitive operations even within authenticated sessions
- Log MFA failures for anomaly detection

### Access Control (Authorization)

**Principles**:
- Deny by default: If no rule explicitly grants access, deny
- Check on every request: Do not rely on UI hiding features
- Server-side enforcement: Client-side checks are supplementary
- Resource-level checks: Verify the user can access THIS specific resource, not just this type of resource

**IDOR prevention**:
```python
# VULNERABLE - No ownership check
@app.route('/api/documents/<doc_id>')
def get_document(doc_id):
    return Document.query.get(doc_id)

# SECURE - Ownership verification
@app.route('/api/documents/<doc_id>')
@login_required
def get_document(doc_id):
    doc = Document.query.filter_by(
        id=doc_id,
        owner_id=current_user.id  # Scoped to user
    ).first_or_404()
    return doc
```

**Role-based access control (RBAC) pattern**:
```python
# Decorator-based authorization
def requires_role(role):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            if not current_user.has_role(role):
                abort(403)
            return f(*args, **kwargs)
        return wrapper
    return decorator

@app.route('/admin/users')
@login_required
@requires_role('admin')
def manage_users():
    ...
```

### CSRF Protection

**Token-based CSRF protection**:
- Generate a cryptographically random token per session
- Include in forms as a hidden field and validate on every state-changing request
- Use `SameSite=Strict` or `SameSite=Lax` cookies as defense-in-depth
- For APIs: Use custom request headers (e.g., `X-CSRF-Token`) that cannot be set by cross-origin requests

**Framework CSRF protection** (use it, do not disable it):
- Django: `{% csrf_token %}` in forms, `@csrf_protect` decorator
- Rails: `protect_from_forgery with: :exception`
- Spring: `CsrfFilter` (enabled by default in Spring Security)
- Express: `csurf` middleware (or custom double-submit cookie)

## Patterns

### Pattern: Authentication Service Isolation
Centralize authentication logic in a single service/module. All authentication decisions flow through this module. This prevents inconsistent authentication checks across endpoints and makes auditing straightforward.

### Pattern: Fail-Secure Authentication
On any error during authentication (database timeout, MFA service unavailable, token parsing failure), deny access. Never let an exception propagate to an implicit "allow."

### Pattern: Constant-Time Comparison
Use constant-time comparison for all security-sensitive string comparisons (tokens, hashes, API keys) to prevent timing attacks.
```python
import hmac
hmac.compare_digest(provided_token, stored_token)
```
```javascript
const crypto = require('crypto');
crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
```

### Pattern: Account Lockout with Progressive Delay
After N failed attempts, implement progressive delays rather than permanent lockout (which enables denial of service). Combine with CAPTCHA and IP-based rate limiting.

## Anti-Patterns

- **Rolling your own auth**: Writing custom password hashing, session management, or token generation instead of using established libraries and frameworks
- **Plaintext password logging**: Logging authentication attempts with the password included, even in "debug" mode
- **Client-side authorization**: Hiding UI elements but not enforcing access control server-side. Attackers do not use your UI
- **Sequential/predictable session IDs**: Using auto-incrementing integers, timestamps, or low-entropy values as session tokens
- **Password length limits**: Capping password length at 8-20 characters. Allow at least 128 characters (bcrypt's 72-byte limit is handled by pre-hashing with SHA-256)
- **Security questions as authentication factors**: "Mother's maiden name" is knowledge, not a factor. It is publicly discoverable and not resettable
- **JWT for sessions**: JWTs as session tokens add complexity (no server-side revocation) without clear benefit for most applications. Server-side sessions with opaque tokens are simpler and more secure
- **Shared secrets across services**: Each service should have its own API key/secret. Compromising one service should not compromise all

## References

- OWASP Authentication Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
- OWASP Session Management Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
- OWASP Password Storage Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
- OWASP CSRF Prevention Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
- OWASP JWT Security Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html
- NIST SP 800-63B: Digital Identity Guidelines (Authentication) -- https://pages.nist.gov/800-63-3/sp800-63b.html
- RFC 6238: TOTP Algorithm -- https://tools.ietf.org/html/rfc6238
- CWE-287: Improper Authentication -- https://cwe.mitre.org/data/definitions/287.html
- CWE-284: Improper Access Control -- https://cwe.mitre.org/data/definitions/284.html

Attribution

HermeticOrmusHermeticOrmus
View sourceSee grades on GitHubMore from HermeticOrmus →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Security Review

Use this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment/sensitive features. Provides comprehensive security checklist and patterns.

2456590 votes

Springboot Security

Java Spring Boot 服务中关于身份验证/授权、验证、CSRF、密钥、标头、速率限制和依赖安全的 Spring Security 最佳实践。

2456590 votes

Summarize Status

Write a short, colloquial summary for a Paperclip summary slot: open with the 1–3 specific, concrete actions the reader needs to take right now to unblock the work, then a brief plain-language status, streaming progress as it works.

953190 votes

Paperclip Task Bridge

Create, comment on, update, and list Paperclip tasks from Hermes using scoped Paperclip API credentials.

953190 votes

Paperclip Evals

Choose, inspect, validate, and report Paperclip Runner or Product E2E evaluations while preserving evidence, provenance, cost, and failure classification.

953190 votes
View all in security →