Authentication¶
WireBuddy supports multiple authentication methods for flexible and secure access control.
Authentication Methods¶
| Method | Security Level | User Experience | Use Case |
|---|---|---|---|
| Passkeys | ⭐⭐⭐⭐⭐ | Excellent | Primary method (recommended) |
| Password + MFA | ⭐⭐⭐⭐ | Good | Backup or traditional preference |
| Password Only | ⭐⭐ | Excellent | Not recommended (weak) |
Authentication Flow¶
Standard Login¶
graph TD
A[User] --> B{Has Passkey?}
B -->|Yes| C[Passkey Login]
B -->|No| D[Username + Password]
D --> E{MFA Enabled?}
E -->|Yes| F[Enter TOTP Code]
E -->|No| G[Logged In]
F --> G
C --> G Password Authentication¶
Password Hashing¶
WireBuddy uses PBKDF2-SHA256:
- Iterations: 600,000 (exceeds OWASP recommendation)
- Salt: Random 32-byte salt per password
- Algorithm: SHA-256
- Verification: Constant-time comparison
Example (Python):
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import hashes
import os
def hash_password(password: str) -> tuple:
salt = os.urandom(32)
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=600_000
)
key = kdf.derive(password.encode())
return salt, key
def verify_password(password: str, salt: bytes, stored_key: bytes) -> bool:
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=600_000
)
try:
kdf.verify(password.encode(), stored_key)
return True
except:
return False
Password Requirements¶
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character
Enforced via regex:
Password Reset¶
- User clicks "Forgot Password"
- Enters username/email
- Reset token emailed (SHA-256, expires in 1 hour)
- User clicks link, enters new password
- Token invalidated, sessions revoked
Multi-Factor Authentication (MFA)¶
TOTP (Time-based One-Time Password)¶
WireBuddy implements RFC 6238 TOTP:
- Algorithm: HMAC-SHA1
- Digits: 6
- Period: 30 seconds
- Window: ±1 period (90 seconds total)
Setup Process:
- User enables MFA
- WireBuddy generates secret:
- User scans QR code or enters secret manually
- User verifies with current code
- Recovery codes generated (10 single-use codes)
Login with MFA:
def verify_totp(user_secret: str, user_code: str) -> bool:
totp = pyotp.TOTP(user_secret)
return totp.verify(user_code, valid_window=1)
Recovery Codes¶
10 single-use codes generated on MFA enrollment:
- Format:
ABCD-1234-EFGH - SHA-256 hashed before storage
- Used in place of TOTP during login
- Regenerate anytime (invalidates old codes)
Passkeys (WebAuthn)¶
See Passkeys Documentation for complete guide.
Brief overview:
- Public key cryptography (no shared secrets)
- Browser/OS integrated (Touch ID, Windows Hello, security keys)
- Phishing resistant
- FIDO2 compliant
Session Management¶
Session Tokens¶
- Generation: Cryptographically random (256 bits)
- Storage: SHA-256 hash in database
- Transmission: Secure, HttpOnly cookie
- Expiry: Configurable (default: 30 minutes)
- Renewal: Automatic on activity
Token Generation:
import secrets
import hashlib
def create_session(user_id: int) -> str:
# Generate token
token = secrets.token_urlsafe(32)
# Hash for storage
token_hash = hashlib.sha256(token.encode()).hexdigest()
# Store in database
store_session(user_id, token_hash, expires_at)
return token
Session Security¶
- HttpOnly: Prevent JavaScript access
- Secure: HTTPS only (when available)
- SameSite: Lax (prevent CSRF)
- Expiry: Sliding window (renews on activity)
- Invalidation: Logout, password change, admin action
Concurrent Sessions¶
Users can have multiple active sessions (different devices).
Settings → Security → Allow Concurrent Sessions
- Enabled: Multiple devices simultaneously
- Disabled: One session per user (logout others on new login)
API Authentication¶
Bearer Tokens¶
Generate API tokens for programmatic access:
Profile → API Tokens → Create
Token Format:
Token Storage:
- SHA-256 hash in database
- Shown only once after creation
- Cannot be retrieved after initial display
Usage:
See API Authentication for details.
CSRF Protection¶
WireBuddy implements double-submit cookie CSRF protection:
How It Works¶
- Login: CSRF token generated and stored in session
- Cookie: Token set in secure cookie
- Request: Frontend includes token in header
- Validation: Server compares header token with cookie
- Origin Check: Verify Origin/Referer header
Implementation:
def generate_csrf_token() -> str:
return secrets.token_urlsafe(32)
def validate_csrf(request_token: str, session_token: str) -> bool:
if not request_token or not session_token:
return False
return secrets.compare_digest(request_token, session_token)
Exempt Endpoints¶
CSRF not required for:
- GET requests (read-only)
- API endpoints with Bearer token
- Webhook endpoints (signed payloads)
Rate Limiting¶
Prevent brute-force attacks:
| Endpoint | Limit | Window | Lockout |
|---|---|---|---|
| Login | 5 attempts | 15 min | Progressive (1m, 5m, 15m) |
| MFA Verify | 5 attempts | 5 min | 5 minutes |
| Password Reset | 3 attempts | 1 hour | 1 hour |
| API (auth) | 100 req | 1 min | 1 minute |
| API (unauth) | 10 req | 1 min | 1 minute |
See Rate Limiting for details.
IP Tracking¶
WireBuddy tracks client IP for security:
Via Reverse Proxy¶
Automatically extracts real IP from X-Forwarded-For:
def get_client_ip(request) -> str:
# Check for X-Forwarded-For from trusted proxy
forwarded_for = request.headers.get('X-Forwarded-For')
if forwarded_for and is_trusted_proxy(request.client.host):
return forwarded_for.split(',')[0].strip()
# Fallback to direct connection
return request.client.host
Trusted proxies:
- Private IP ranges (auto-detected)
- Custom list (configurable)
Use Cases¶
- Rate limiting (per IP)
- Brute-force detection
- Login history
- Audit logging
Security Headers¶
WireBuddy sets security headers automatically:
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Content-Security-Policy: default-src 'self'; ...
Audit Logging¶
All authentication events are logged:
{
"timestamp": "2026-03-15T14:30:00Z",
"event": "login_success",
"user": "admin",
"ip": "203.0.113.42",
"method": "password_mfa",
"user_agent": "Mozilla/5.0 ...",
"session_id": "abc123...",
"metadata": {
"mfa_method": "totp"
}
}
Logged Events:
- Login success/failure
- Logout
- Password change
- MFA enrollment/use
- Passkey registration/use
- API token creation/revocation
- Session revocation
Access logs:
Profile → Security → Login History
Or via API:
Best Practices¶
For Users¶
- Use passkeys when possible (most secure)
- Enable MFA if using password
- Use strong passwords (12+ characters, unique)
- Review active sessions regularly
- Revoke unused API tokens
- Monitor login history for suspicious activity
For Admins¶
- Enforce MFA for admin accounts
- Set reasonable session timeout (30 minutes)
- Enable rate limiting (always on)
- Review audit logs weekly
- Disable Swagger UI in production (if not needed)
- Use HTTPS always (enable Force HTTPS)
- Configure trusted proxies correctly
Troubleshooting¶
See Troubleshooting Guide for common authentication problems.
Next Steps¶
- Passkeys (WebAuthn) - Passwordless authentication
- Rate Limiting - Brute-force protection
- Security Overview - Complete security documentation
- User Management - Managing users