Authentication & Authorization
Comprehensive guide to SysManage's JWT-based authentication system, role-based access control, multi-factor authentication, and session management.
Authentication Overview
SysManage implements a robust multi-layered authentication and authorization system designed for enterprise environments. The system combines JWT-based stateless authentication with comprehensive role-based access control (RBAC) to ensure secure access to infrastructure management capabilities.
Authentication Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Authentication Flow │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ User Login │ │ JWT Service │ │ RBAC Authorization │ │
│ │ (Web/API) │ │ (Token Gen) │ │ (Role Validation) │ │
│ └─────────────┘ └──────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
│ │ Password │ │ Session │ │ Multi-Factor Auth │ │
│ │ Validation │ │ Management │ │ (Optional MFA) │ │
│ └─────────────┘ └──────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL User Store │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
JWT Authentication
JWT Implementation
SysManage uses JSON Web Tokens (JWT) for stateless authentication, providing scalability and security benefits for distributed deployments.
JWT Token Structure
# JWT Header
{
"alg": "HS256",
"typ": "JWT"
}
# JWT Payload
{
"sub": "user_id",
"username": "admin",
"email": "admin@company.com",
"roles": ["admin", "operator"],
"permissions": ["read:hosts", "write:hosts", "manage:users"],
"iat": 1634567890,
"exp": 1634571490,
"jti": "unique-token-id"
}
# JWT Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
Token Generation Process
- User Authentication: Validate credentials against user database
- Role Resolution: Query user roles and permissions from RBAC system
- Token Creation: Generate JWT with user claims and permissions
- Token Signing: Sign token with server secret key
- Response: Return signed JWT to client with expiration information
JWT Configuration
# JWT Settings in server configuration
JWT_SECRET_KEY="your-secure-secret-key-here"
JWT_ALGORITHM="HS256"
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
JWT_ISSUER="sysmanage-server"
JWT_AUDIENCE="sysmanage-clients"
# Token rotation settings
JWT_ALLOW_REFRESH=true
JWT_REFRESH_THRESHOLD_MINUTES=5
JWT_BLACKLIST_ENABLED=true
Token Rotation & Security
SysManage implements automatic token rotation to enhance security:
Automatic Rotation
- Tokens automatically refreshed when 5 minutes from expiry
- Refresh tokens issued with longer validity periods
- Old tokens invalidated after successful refresh
Token Blacklisting
- Revoked tokens stored in blacklist
- All API requests validate against blacklist
- Automatic cleanup of expired blacklist entries
Token Validation Flow
# FastAPI JWT validation middleware
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer
import jwt
security = HTTPBearer()
async def validate_token(token: str = Depends(security)):
try:
# Decode and validate JWT
payload = jwt.decode(
token.credentials,
JWT_SECRET_KEY,
algorithms=[JWT_ALGORITHM],
audience=JWT_AUDIENCE,
issuer=JWT_ISSUER
)
# Check token blacklist
if await is_token_blacklisted(payload.get('jti')):
raise HTTPException(401, "Token has been revoked")
# Validate token expiration
if payload.get('exp', 0) < time.time():
raise HTTPException(401, "Token has expired")
return payload
except jwt.InvalidTokenError:
raise HTTPException(401, "Invalid token")
except Exception as e:
raise HTTPException(401, f"Token validation failed: {str(e)}")
Role-Based Access Control (RBAC)
RBAC Architecture
SysManage implements a comprehensive RBAC system with hierarchical roles and granular permissions.
RBAC Data Model
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Users │────▶│ Roles │────▶│ Permissions │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ - user_id │ - role_id │ - permission_id
│ - username │ - role_name │ - resource
│ - email │ - description │ - action
│ - password_hash │ - created_at │ - scope
│ - created_at │ - updated_at │ - description
│ - is_active │ │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└───────┬───────────┴───────┬───────────┘
│ │
┌───────▼────────┐ ┌───────▼────────┐
│ User_Roles │ │ Role_Permissions│
│ │ │ │
│ - user_id │ │ - role_id │
│ - role_id │ │ - permission_id │
│ - granted_by │ │ - granted_at │
│ - granted_at │ └─────────────────┘
└────────────────┘
Default Roles
🔐 Admin
Full system access
- User management
- System configuration
- All host operations
- Security settings
- Audit log access
⚙️ Operator
Operations access
- Host management
- Package operations
- System monitoring
- Task execution
- Limited user management
👁️ Viewer
Read-only access
- View hosts and status
- Read package information
- Access monitoring data
- View task results
- Export reports
📊 Auditor
Audit and compliance
- Access audit logs
- View security events
- Generate compliance reports
- Review user activities
- Monitor system changes
Permission System
Permissions follow a resource:action pattern for granular access control:
RBAC Implementation
# Permission decorator for API endpoints
from functools import wraps
from fastapi import HTTPException
def require_permission(resource: str, action: str):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
# Get current user from JWT token
current_user = kwargs.get('current_user')
# Check if user has required permission
if not await has_permission(current_user, resource, action):
raise HTTPException(
status_code=403,
detail=f"Permission denied: {resource}:{action}"
)
return await func(*args, **kwargs)
return wrapper
return decorator
# Usage example
@app.post("/api/hosts/{host_id}/approve")
@require_permission("hosts", "approve")
async def approve_host(host_id: int, current_user: User = Depends(get_current_user)):
# Approve host logic here
pass
Multi-Factor Authentication (MFA)
MFA Implementation
SysManage supports Time-based One-Time Password (TOTP) multi-factor authentication for enhanced security.
Supported MFA Methods
📱 TOTP (Time-based OTP)
- Compatible with Google Authenticator
- Microsoft Authenticator support
- Authy and other TOTP apps
- 30-second token rotation
📧 Email OTP
- Email-based one-time passwords
- 5-minute token validity
- Rate limiting for security
- Backup method for TOTP
🔑 Recovery Codes
- Single-use recovery codes
- 10 codes generated per user
- Secure storage and hashing
- Emergency access capability
MFA Enrollment Process
- User Initiates: User requests MFA setup from profile settings
- Secret Generation: Server generates unique TOTP secret key
- QR Code Display: QR code presented for authenticator app setup
- Verification: User enters TOTP code to verify setup
- Recovery Codes: System generates and displays recovery codes
- Activation: MFA becomes active after successful verification
MFA Configuration
# MFA settings in server configuration
MFA_ENABLED=true
MFA_REQUIRED_FOR_ADMIN=true
MFA_TOTP_ISSUER="SysManage"
MFA_TOKEN_VALIDITY_SECONDS=30
MFA_BACKUP_CODES_COUNT=10
MFA_EMAIL_OTP_VALIDITY_MINUTES=5
MFA_MAX_ATTEMPTS=3
MFA_LOCKOUT_DURATION_MINUTES=15
# TOTP implementation
import pyotp
import qrcode
def generate_totp_secret():
return pyotp.random_base32()
def generate_qr_code(user_email: str, secret: str):
totp_uri = pyotp.totp.TOTP(secret).provisioning_uri(
name=user_email,
issuer_name="SysManage"
)
qr = qrcode.QRCode(version=1, box_size=10, border=5)
qr.add_data(totp_uri)
qr.make(fit=True)
return qr.make_image(fill_color="black", back_color="white")
Session Management
Session Architecture
SysManage implements stateless session management using JWT tokens with additional security features.
Session Features
Token-Based Sessions
- Stateless JWT-based sessions
- No server-side session storage
- Horizontal scaling friendly
- Cross-domain support
Session Security
- Secure HTTP-only cookies
- CSRF protection tokens
- SameSite cookie attributes
- Automatic session timeout
Session Monitoring
- Active session tracking
- Concurrent session limits
- Session activity logging
- Suspicious activity detection
Session Configuration
# Session configuration
SESSION_SECURE_COOKIES=true
SESSION_HTTPONLY_COOKIES=true
SESSION_SAMESITE="Strict"
SESSION_DOMAIN=".sysmanage.local"
SESSION_MAX_AGE_HOURS=8
SESSION_IDLE_TIMEOUT_MINUTES=30
SESSION_MAX_CONCURRENT=5
SESSION_TRACK_IP_CHANGES=true
# Session cookie implementation
from fastapi import Response
def set_session_cookie(response: Response, token: str):
response.set_cookie(
key="sysmanage_session",
value=token,
httponly=True,
secure=True,
samesite="strict",
max_age=SESSION_MAX_AGE_HOURS * 3600,
domain=SESSION_DOMAIN
)
Password Policies
Password Requirements
SysManage enforces configurable password policies to ensure strong authentication credentials.
Default Password Policy
- Minimum Length: 12 characters
- Character Classes: At least 3 of the following:
- Uppercase letters (A-Z)
- Lowercase letters (a-z)
- Numbers (0-9)
- Special characters (!@#$%^&*)
- Dictionary Check: Not common dictionary words
- History: Cannot reuse last 12 passwords
- Expiration: 90 days (configurable)
- Account Lockout: 5 failed attempts
Password Policy Configuration
# Password policy settings
PASSWORD_MIN_LENGTH=12
PASSWORD_REQUIRE_UPPERCASE=true
PASSWORD_REQUIRE_LOWERCASE=true
PASSWORD_REQUIRE_NUMBERS=true
PASSWORD_REQUIRE_SPECIAL=true
PASSWORD_MIN_CHAR_CLASSES=3
PASSWORD_CHECK_DICTIONARY=true
PASSWORD_HISTORY_COUNT=12
PASSWORD_EXPIRY_DAYS=90
PASSWORD_WARN_DAYS=7
# Account lockout settings
ACCOUNT_LOCKOUT_ATTEMPTS=5
ACCOUNT_LOCKOUT_DURATION_MINUTES=30
ACCOUNT_LOCKOUT_RESET_TIME_MINUTES=60
# Password validation implementation
import re
from passlib.hash import argon2
class PasswordPolicy:
def __init__(self):
self.min_length = PASSWORD_MIN_LENGTH
self.require_classes = PASSWORD_MIN_CHAR_CLASSES
def validate(self, password: str, user_data: dict = None) -> tuple[bool, list]:
errors = []
# Length check
if len(password) < self.min_length:
errors.append(f"Password must be at least {self.min_length} characters")
# Character class checks
classes = 0
if re.search(r'[A-Z]', password):
classes += 1
if re.search(r'[a-z]', password):
classes += 1
if re.search(r'[0-9]', password):
classes += 1
if re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
classes += 1
if classes < self.require_classes:
errors.append(f"Password must contain at least {self.require_classes} character classes")
# Dictionary check
if self.is_common_password(password):
errors.append("Password is too common")
return len(errors) == 0, errors
Authentication Security Monitoring
Security Events
SysManage logs and monitors authentication-related security events for threat detection and compliance.
Monitored Events
Authentication Events
- Successful logins
- Failed login attempts
- Account lockouts
- Password changes
- MFA enrollment/changes
Suspicious Activities
- Multiple failed attempts
- Login from new locations
- Concurrent sessions
- Privilege escalation attempts
- Token manipulation
Administrative Actions
- User creation/deletion
- Role assignments
- Permission changes
- Security setting modifications
- Audit log access
Alert Configuration
# Security alert thresholds
ALERT_FAILED_LOGINS_THRESHOLD=5
ALERT_FAILED_LOGINS_WINDOW_MINUTES=10
ALERT_NEW_LOCATION_LOGIN=true
ALERT_CONCURRENT_SESSIONS_THRESHOLD=3
ALERT_ADMIN_ACTIONS=true
ALERT_MFA_BYPASS_ATTEMPTS=true
# Event logging structure
{
"timestamp": "2024-01-15T10:30:00Z",
"event_type": "authentication",
"event_subtype": "login_failed",
"user_id": "user123",
"username": "jdoe",
"ip_address": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"details": {
"reason": "invalid_password",
"attempt_count": 3,
"location": "New York, US"
},
"severity": "medium",
"source": "web_ui"
}
Integration Examples
External Authentication Providers
SysManage can integrate with external authentication systems for enterprise environments.
LDAP/Active Directory Integration
# LDAP configuration
LDAP_ENABLED=true
LDAP_SERVER="ldap://dc.company.com:389"
LDAP_BIND_DN="CN=sysmanage,OU=Service Accounts,DC=company,DC=com"
LDAP_BIND_PASSWORD="secure-password"
LDAP_USER_SEARCH_BASE="OU=Users,DC=company,DC=com"
LDAP_USER_SEARCH_FILTER="(&(objectClass=user)(sAMAccountName={username}))"
LDAP_GROUP_SEARCH_BASE="OU=Groups,DC=company,DC=com"
LDAP_ROLE_MAPPING='{"CN=SysManage Admins,OU=Groups,DC=company,DC=com": "admin"}'
# LDAP authentication implementation
import ldap3
async def authenticate_ldap(username: str, password: str):
try:
server = ldap3.Server(LDAP_SERVER)
user_dn = await find_user_dn(username)
conn = ldap3.Connection(server, user_dn, password)
if conn.bind():
user_groups = await get_user_groups(conn, user_dn)
roles = map_groups_to_roles(user_groups)
return create_user_session(username, roles)
else:
return None
except Exception as e:
logger.error(f"LDAP authentication failed: {e}")
return None
SAML 2.0 Integration
# SAML configuration
SAML_ENABLED=true
SAML_ENTITY_ID="https://sysmanage.company.com"
SAML_SSO_URL="https://idp.company.com/sso"
SAML_SLO_URL="https://idp.company.com/slo"
SAML_X509_CERT="/path/to/idp-cert.pem"
SAML_ATTRIBUTE_MAPPING='{"email": "EmailAddress", "roles": "Groups"}'
# SAML response handling
from onelogin.saml2.auth import OneLogin_Saml2_Auth
@app.post("/auth/saml/acs")
async def saml_acs(request: Request):
auth = OneLogin_Saml2_Auth(request, saml_settings)
auth.process_response()
if auth.is_authenticated():
attributes = auth.get_attributes()
email = attributes.get('EmailAddress', [None])[0]
groups = attributes.get('Groups', [])
user = await get_or_create_user(email, groups)
token = create_jwt_token(user)
return {"access_token": token, "token_type": "bearer"}
else:
raise HTTPException(401, "SAML authentication failed")
Troubleshooting Authentication
Common Issues
Token Expired Errors
- Check system clock synchronization
- Verify JWT expiration settings
- Ensure token refresh is working
- Check client token storage
MFA Setup Problems
- Verify authenticator app time sync
- Check QR code generation
- Validate TOTP secret storage
- Test backup recovery codes
RBAC Permission Errors
- Verify user role assignments
- Check permission definitions
- Validate JWT claims
- Review role hierarchy
External Auth Integration
- Test LDAP connectivity
- Verify certificate validity
- Check attribute mappings
- Review firewall rules
Diagnostic Commands
# Test JWT token validation
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://localhost:8000/api/auth/validate
# Check user permissions
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://localhost:8000/api/auth/permissions
# Test LDAP connectivity
ldapsearch -H ldap://your-server:389 -D "bind-dn" -w "password" \
-b "search-base" "(objectClass=user)"
# View authentication logs
tail -f /var/log/sysmanage/auth.log | grep "authentication"