Authentication
| Field | Value |
|---|---|
| Document ID | ASCEND-SEC-003 |
| Version | 1.0.0 |
| Last Updated | December 19, 2025 |
| Author | Ascend Engineering Team |
| Publisher | OW-KAI Technologies Inc. |
| Classification | Enterprise Client Documentation |
| Compliance | SOC 2 CC6.1/CC6.2, PCI-DSS 7.1/8.3, HIPAA 164.312, NIST 800-53 AC-2/SI-4 |
Reading Time: 10 minutes | Skill Level: Intermediate
Overview
ASCEND provides dual authentication supporting both JWT (admin UI) and API keys (SDK). The system implements banking-level security controls including token blacklisting, session management, and MFA enforcement.
Authentication Methods
| Method | Use Case | Token Type | MFA |
|---|---|---|---|
| JWT Cookie | Admin UI | Session token | Required |
| Bearer Token | Cognito/SSO | JWT | Delegated |
| API Key | SDK | Hashed key | Optional |
Dual Authentication Flow
+---------------------------------------------------------------------------------+
| DUAL AUTHENTICATION FLOW |
+---------------------------------------------------------------------------------+
| |
| REQUEST ARRIVES |
| | |
| v |
| +------------------------+ |
| | CHECK JWT COOKIE | 1. Session cookie from admin UI |
| +------------------------+ |
| | (not found) |
| v |
| +------------------------+ |
| | CHECK BEARER TOKEN | 2. Authorization: Bearer <token> |
| +------------------------+ |
| | |
| +-- JWT (3 parts)? ---> Validate with Cognito JWKS |
| | |
| +-- API Key? ---------> Verify hash, check rate limit |
| | |
| v (not found) |
| +------------------------+ |
| | CHECK X-API-KEY | 3. X-API-Key: <api_key> |
| +------------------------+ |
| | (not found) |
| v |
| +------------------------+ |
| | 401 UNAUTHORIZED | |
| +------------------------+ |
| |
+---------------------------------------------------------------------------------+
JWT Session Management
Login
curl -X POST "https://pilot.owkai.app/api/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "user@company.com",
"password": "securePassword123!"
}'
Response:
{
"success": true,
"user": {
"id": 123,
"email": "user@company.com",
"role": "admin",
"organization_id": 1
},
"requires_mfa": true,
"mfa_session_token": "<temporary_token>"
}
MFA Verification
curl -X POST "https://pilot.owkai.app/api/auth/mfa/verify" \
-H "Content-Type: application/json" \
-d '{
"mfa_session_token": "<temporary_token>",
"totp_code": "123456"
}'
Response (sets session cookie):
{
"success": true,
"message": "Authentication successful",
"user": {
"id": 123,
"email": "user@company.com",
"role": "admin"
}
}
Logout
curl -X POST "https://pilot.owkai.app/api/auth/logout" \
-H "Cookie: owai_session=<session_token>"
Response:
{
"success": true,
"message": "Logged out successfully",
"tokens_revoked": 1
}
Token Security Features
Token Blacklist (AUTH-001)
# Source: security/enterprise_security.py:59
class TokenBlacklist:
"""
Thread-safe token blacklist for immediate revocation.
Banking-level security requires tokens to be revokable instantly.
"""
def revoke(self, token_jti: str, expires_at: datetime) -> None:
"""Revoke a token by its JTI (JWT ID)."""
with self._lock:
self._blacklist.add(token_jti)
self._expiry[token_jti] = expires_at
def is_revoked(self, token_jti: str) -> bool:
"""Check if a token has been revoked."""
return token_jti in self._blacklist
def revoke_all_user_tokens(self, user_id: int, db: Session) -> int:
"""Revoke ALL tokens for a user (logout from all devices)."""
pass
Refresh Token Rotation (AUTH-003)
# Source: security/enterprise_security.py:231
class RefreshTokenManager:
"""
Manages refresh token rotation for banking-level security.
Each time a refresh token is used, a new one is issued
and the old one is invalidated.
"""
def validate_and_rotate(self, token_jti: str) -> bool:
"""
Validate refresh token hasn't been used and mark it as used.
Returns True if token is valid (first use), False if reused.
"""
if self.is_used(token_jti):
return False
self.mark_used(token_jti)
return True
Session Fixation Prevention (AUTH-005)
# Source: security/enterprise_security.py:341
def regenerate_session(response: Response, old_session_id: Optional[str] = None) -> str:
"""
Regenerate session ID after authentication (prevents session fixation).
Returns new 256-bit cryptographically secure session ID.
"""
new_session_id = secrets.token_hex(32)
return new_session_id
Account Lockout
Lockout Policy (AUTH-004)
# Source: security/enterprise_security.py:285
class AccountLockoutManager:
"""
Manages account lockouts with exponential backoff.
Banking security requires:
- Lock after 5 failed attempts
- Exponential backoff: 5min, 15min, 1hr, 24hr
- Automatic unlock after cooldown period
"""
MAX_ATTEMPTS = 5
BACKOFF_MULTIPLIER = 3
INITIAL_LOCKOUT_MINUTES = 5
MAX_LOCKOUT_HOURS = 24
def calculate_lockout_duration(self, consecutive_lockouts: int) -> timedelta:
"""Calculate lockout duration with exponential backoff."""
minutes = self.INITIAL_LOCKOUT_MINUTES * (self.BACKOFF_MULTIPLIER ** consecutive_lockouts)
max_minutes = self.MAX_LOCKOUT_HOURS * 60
return timedelta(minutes=min(minutes, max_minutes))
Lockout Schedule
| Lockout # | Duration | Total Wait |
|---|---|---|
| 1 | 5 minutes | 5 minutes |
| 2 | 15 minutes | 20 minutes |
| 3 | 45 minutes | 65 minutes |
| 4+ | 24 hours | 24+ hours |
Concurrent Session Control
Session Limits (AUTH-011)
# Source: security/enterprise_security.py:530
class ConcurrentSessionManager:
"""
Manages concurrent session limits per user.
Banking security typically limits to 3-5 concurrent sessions.
When limit exceeded, oldest session is terminated.
"""
DEFAULT_MAX_SESSIONS = 5
def register_session(self, user_id, session_id, max_sessions=5):
"""
Register a new session, potentially removing oldest if limit exceeded.
Returns session ID that was removed (if any).
"""
pass
CSRF Protection
Double-Submit Cookie (AUTH-009)
# Source: security/enterprise_security.py:419
class CSRFValidator:
"""CSRF protection using double-submit cookie pattern."""
CSRF_COOKIE_NAME = "owai_csrf"
CSRF_HEADER_NAME = "X-CSRF-Token"
@staticmethod
def validate(request: Request) -> bool:
"""
Validate CSRF token using double-submit cookie pattern.
Uses constant-time comparison to prevent timing attacks.
"""
cookie_token = request.cookies.get(CSRFValidator.CSRF_COOKIE_NAME)
header_token = request.headers.get(CSRFValidator.CSRF_HEADER_NAME)
return secrets.compare_digest(cookie_token, header_token)
Rate Limiting
Authentication Rate Limits
# Source: security/rate_limiter.py:33
RATE_LIMITS = {
# Authentication - STRICT limits
"auth_login": "5/minute",
"auth_refresh": "10/minute",
"auth_csrf": "20/minute",
# Password operations - VERY STRICT
"auth_password_change": "3/minute",
"auth_password_reset": "3/minute",
# MFA operations - STRICT
"auth_mfa_setup": "5/minute",
"auth_mfa_verify": "10/minute",
# Account operations
"auth_register": "3/minute",
"auth_logout": "30/minute"
}
Cognito Integration
Token Validation
# Source: dependencies_api_keys.py:421
# Cognito JWT verification using JWKS public keys
user_context = validate_cognito_token(token, db)
# Returns:
{
"user_id": 123,
"email": "user@company.com",
"role": "admin",
"organization_id": 1,
"cognito_user_id": "abc-123-xyz"
}
Session Creation
curl -X POST "https://pilot.owkai.app/api/auth/cognito-session" \
-H "Authorization: Bearer <cognito_token>"
Response (sets session cookie):
{
"success": true,
"user": {
"id": 123,
"email": "user@company.com",
"organization_id": 1
},
"session_expires_at": "2025-12-15T18:30:00Z"
}
Security Headers
Response Headers (AUTH-012)
# Source: security/enterprise_security.py:606
SECURITY_HEADERS = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
"Content-Security-Policy": "default-src 'self'; frame-ancestors 'none';",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "geolocation=(), microphone=(), camera=()"
}
Best Practices
1. Use Secure Cookies
# Session cookies should be:
{
"httponly": True, # Prevent XSS access
"secure": True, # HTTPS only
"samesite": "strict" # CSRF protection
}
2. Implement Token Expiration
# Short-lived access tokens
{
"access_token_expires": "15 minutes",
"refresh_token_expires": "7 days"
}
3. Monitor Failed Logins
# Alert on suspicious activity
if failed_attempts > 3:
alert_security_team(user_email, ip_address)
4. Rotate Secrets Regularly
# JWT secrets should be rotated
{
"rotation_period": "90 days",
"minimum_entropy": "256 bits"
}
Next Steps
Document Version: 1.0.0 | Last Updated: December 2025