Skip to main content

Authentication

FieldValue
Document IDASCEND-SEC-003
Version2026.04
Last UpdatedApril 2026
AuthorAscend Engineering Team
PublisherOW-KAI Technologies Inc.
ClassificationEnterprise Client Documentation
ComplianceSOC 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.

Fail-Secure Behavior

If Cognito is unreachable or token validation fails for any reason, ASCEND returns HTTP 401 and rejects the request. There is no fallback authentication path.

Authentication Methods

MethodUse CaseToken TypeMFA
JWT CookieAdmin UISession tokenRequired
Bearer TokenCognito/SSOJWTDelegated
API KeySDKHashed keyOptional

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 #DurationTotal Wait
15 minutes5 minutes
215 minutes20 minutes
345 minutes65 minutes
4+24 hours24+ 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

# 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

  • API Keys — SDK authentication
  • SSO — Enterprise SSO integration
  • RBAC — Role-based access control

Document Version: 2026.04 | Last Updated: April 2026