Executive Summary

AIUsagePlatform uses JWT (JSON Web Token) bearer authentication with RS256 (RSA + SHA256) signing. Tokens carry identity claims including UserId, OrganizationId, Role, and Permissions for distributed validation without database lookups.

βœ… RS256 Signing
Asymmetric keys, key rotation ready
βœ… Short-Lived
Access token: 15 min, Refresh: 7 days
βœ… Tenant Context
OrganizationId embedded in claims
⚠️ No Token Revocation
Compromised tokens valid until expiry

πŸ”„ Authentication Flow

JWT Authentication Flow ═══════════════════════════════════════════════════════════════════════════════ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Client β”‚ β”‚ Identity Server β”‚ β”‚ (Angular)β”‚ β”‚ (AuthController) β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ POST /api/auth/login β”‚ β”‚ { email, password } β”‚ │────────────────────────────────────────────────────────►│ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Validate Password β”‚ β”‚ β”‚ β”‚ Check User Status β”‚ β”‚ β”‚ β”‚ Load Roles/Perms β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Generate Tokens β”‚ β”‚ β”‚ β”‚ ─────────────── β”‚ β”‚ β”‚ β”‚ Access Token (JWT)β”‚ β”‚ β”‚ β”‚ β€’ Exp: 15 min β”‚ β”‚ β”‚ β”‚ β€’ Claims: sub, β”‚ β”‚ β”‚ β”‚ org, role, perm β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Refresh Token β”‚ β”‚ β”‚ β”‚ β€’ Exp: 7 days β”‚ β”‚ β”‚ β”‚ β€’ Stored in DB β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ { accessToken, refreshToken, user } β”‚ β”‚ │◄───────────────────────────────────────│ β”‚ β”‚ β”‚ ─────┴────────────────────────────────────────────────────────┴────────────── SUBSEQUENT API CALLS: ─────────────────────────────────────────────────────────────────────────────── β”‚ GET /api/admindashboard β”‚ β”‚ Authorization: Bearer eyJhbGciOiJSUzI1Ni... β”‚ │────────────────────────────────────────────────────────►│ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ [Authorize] β”‚ β”‚ β”‚ β”‚ Validate JWT: β”‚ β”‚ β”‚ β”‚ β€’ Signature (RS256)β”‚ β”‚ β”‚ β”‚ β€’ Expiration β”‚ β”‚ β”‚ β”‚ β€’ Issuer/Audience β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Extract Claims: β”‚ β”‚ β”‚ β”‚ β€’ sub: user-id β”‚ β”‚ β”‚ β”‚ β€’ org: org-id β”‚ β”‚ β”‚ β”‚ β€’ role: Admin β”‚ β”‚ β”‚ β”‚ β€’ perm: [...] β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ MultiTenantMiddlewareβ”‚ β”‚ β”‚ β”‚ Validate org access β”‚ β”‚ β”‚ β”‚ Attach tenant contextβ”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ { dashboard data } β”‚ β”‚ │◄───────────────────────────────────────│ β”‚ β”‚ β”‚

πŸ“‹ JWT Claims Structure

ClaimTypeDescriptionExample
substring (GUID)Subject (User ID)usr_12345678-...
emailstringUser email addressadmin@acme.com
orgstring (GUID)Organization ID (tenant)org_87654321-...
rolestringPrimary role nameAdmin
role_levelintegerRole hierarchy level50
permissionsJSON arrayGranted permissions["Users.View", "Reports.Create"]
issstringToken issuerAIUsagePlatform
audstringToken audienceAIUsagePlatform.API
expUnix timestampExpiration time1704067200
iatUnix timestampIssued at time1704066300
jtistring (GUID)Unique token IDtok_abc123...

πŸ” Token Security Properties

Access Token
  • βœ“ Lifetime: 15 minutes
  • βœ“ Algorithm: RS256 (RSA 2048-bit)
  • βœ“ Key ID: kid header for rotation
  • βœ“ Storage: Memory only (Angular)
Refresh Token
  • βœ“ Lifetime: 7 days
  • βœ“ Storage: HTTP-only secure cookie
  • βœ“ Database: Hashed in RefreshTokens table
  • βœ“ Rotation: New token on each use
Security Headers
  • βœ“ Strict-Transport-Security
  • βœ“ X-Content-Type-Options: nosniff
  • βœ“ X-Frame-Options: DENY
  • βœ“ Content-Security-Policy

βœ… Token Validation Pipeline

JWT Validation Pipeline (ASP.NET Core) ═══════════════════════════════════════════════════════════════════════════════ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ASP.NET Core Middleware Pipeline β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ 1. Authentication Middleware β”‚ β”‚ β”œβ”€β”€ Extract Bearer token from Authorization header β”‚ β”‚ β”œβ”€β”€ Parse JWT headers (alg, typ, kid) β”‚ β”‚ β”œβ”€β”€ Fetch public key from JWKS endpoint (cached) β”‚ β”‚ β”œβ”€β”€ Verify RS256 signature β”‚ β”‚ └── Build ClaimsPrincipal from JWT claims β”‚ β”‚ β”‚ β”‚ 2. MultiTenantIsolationMiddleware β”‚ β”‚ β”œβ”€β”€ Extract "org" claim from Identity β”‚ β”‚ β”œβ”€β”€ If SuperAdmin: Bypass tenant checks (special handling) β”‚ β”‚ β”œβ”€β”€ Validate organization exists and is Active β”‚ β”‚ β”œβ”€β”€ Check subscription status (not Expired/Suspended) β”‚ β”‚ └── Attach X-Tenant-* headers to response β”‚ β”‚ β”‚ β”‚ 3. Authorization Middleware β”‚ β”‚ β”œβ”€β”€ [Authorize] β†’ Check authenticated β”‚ β”‚ β”œβ”€β”€ [Authorize(Roles="Admin")] β†’ Check role claim β”‚ β”‚ └── [HasPermission] β†’ Check permissions claim β”‚ β”‚ β”‚ β”‚ 4. Rate Limiting Middleware β”‚ β”‚ β”œβ”€β”€ Identify client by UserId from claims β”‚ β”‚ β”œβ”€β”€ Check rate limit counters (Redis) β”‚ β”‚ └── Reject if exceeded (429 Too Many Requests) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

⚠️ Security Concerns

⚠
No Token Revocation List
Compromised tokens remain valid until expiry. Need Redis blacklist for logout/scenarios.
⚠
Refresh Token Long Lifetime
7-day refresh token increases window of compromise. Consider shorter (1-3 days) with sliding.
βœ“
RS256 Asymmetric Signing
Private key on server only. Public key can be rotated without client changes. Good practice.
βœ“
HTTP-Only Refresh Token
Refresh token stored in secure, HTTP-only cookie prevents XSS theft.

πŸ’‘ Recommended Enhancements

Token Revocation (Redis)

Store revoked token JTIs in Redis with TTL matching token expiry. Check on each request.

Recommended High

Device Fingerprinting

Bind tokens to device fingerprint (hash). Reject if fingerprint mismatch (token theft detection).

Recommended Medium

Concurrent Session Limit

Enforce max 3-5 concurrent sessions per user. Invalidate oldest on new login.

Recommended Medium