Architecture Overview¶
Understanding AuthVital's system design and how components interact.
System Overview¶
AuthVital is a B2B Identity Provider built as a multi-tenant OAuth 2.0/OIDC compliant authentication platform. It provides:
- Authentication: OAuth 2.0 with PKCE, password login, SSO
- Authorization: Role-based access control (RBAC) with permissions
- Multi-tenancy: Complete tenant isolation with membership management
- Licensing: Flexible license pool system for SaaS applications
- Extensibility: Webhooks and SDK for seamless integration
High-Level Architecture¶
graph TB
subgraph "Client Applications"
SPA[React SPA<br/>@authvital/sdk/client]
Mobile[Mobile App]
Server[Backend Server<br/>@authvital/sdk/server]
end
subgraph "AuthVital Platform"
direction TB
subgraph "API Layer"
OAuth[OAuth/OIDC<br/>Endpoints]
Auth[Auth<br/>Controller]
API[REST API<br/>Controllers]
end
subgraph "Service Layer"
AuthSvc[Auth Service]
OAuthSvc[OAuth Service]
TenantSvc[Tenant Service]
LicenseSvc[License Service]
WebhookSvc[Webhook Service]
end
subgraph "Data Layer"
Prisma[Prisma ORM]
DB[(PostgreSQL)]
end
subgraph "Security"
JWT[JWT/JOSE]
MFA[MFA - TOTP]
SSO[SSO Providers]
end
end
subgraph "External"
Google[Google OAuth]
Microsoft[Microsoft OAuth]
SendGrid[SendGrid Email]
end
SPA -->|OAuth Flow| OAuth
Mobile -->|OAuth Flow| OAuth
Server -->|JWT Validation| API
Server -->|Webhooks| WebhookSvc
OAuth --> OAuthSvc
Auth --> AuthSvc
API --> TenantSvc
API --> LicenseSvc
AuthSvc --> Prisma
OAuthSvc --> JWT
TenantSvc --> Prisma
LicenseSvc --> Prisma
WebhookSvc --> Prisma
Prisma --> DB
SSO --> Google
SSO --> Microsoft
AuthSvc --> SendGrid Core Components¶
1. OAuth/OIDC Server¶
The heart of AuthVital - a fully compliant OAuth 2.0 and OpenID Connect server.
| Endpoint | Purpose |
|---|---|
GET /oauth/authorize | Start authorization flow |
POST /oauth/token | Exchange code for tokens |
GET /oauth/userinfo | Get user profile (OIDC) |
GET /.well-known/openid-configuration | OIDC discovery |
GET /.well-known/jwks.json | Public signing keys |
Key Features: - PKCE (Proof Key for Code Exchange) for SPAs - Refresh token rotation - Tenant-scoped tokens - Automatic key rotation
2. Multi-Tenant Data Model¶
erDiagram
User ||--o{ Membership : "belongs to"
Tenant ||--o{ Membership : "has"
Membership ||--o{ MembershipRole : "has"
Role ||--o{ MembershipRole : "assigned via"
Role ||--o{ RolePermission : "grants"
Permission ||--o{ RolePermission : "granted by"
User {
string id PK
string email UK
string passwordHash
boolean mfaEnabled
}
Tenant {
string id PK
string name
string slug UK
enum mfaPolicy
}
Membership {
string id PK
string userId FK
string tenantId FK
enum status
}
Role {
string id PK
string slug
string applicationId FK
} 3. Licensing Engine¶
AuthVital includes a sophisticated license pool system for SaaS applications:
graph LR
subgraph "License Pool System"
App[Application]
LT[License Types<br/>Pro, Enterprise, etc.]
Sub[Subscriptions<br/>Tenant purchases]
Assign[Assignments<br/>User licenses]
end
App -->|defines| LT
LT -->|creates| Sub
Sub -->|enables| Assign
subgraph "Modes"
Free[FREE<br/>Auto-provision all]
Seat[PER_SEAT<br/>Assign individually]
Wide[TENANT_WIDE<br/>All members access]
end Licensing Modes:
| Mode | Description | Use Case |
|---|---|---|
FREE | All users get access automatically | Free tier, open products |
PER_SEAT | Each user needs an assigned seat | Traditional SaaS licensing |
TENANT_WIDE | Tenant subscribes, all members access | Team/org subscriptions |
4. Authentication Flow¶
sequenceDiagram
participant U as User
participant C as Client App
participant A as AuthVital
participant DB as Database
U->>C: Click "Login"
C->>A: GET /oauth/authorize<br/>(client_id, redirect_uri, PKCE)
A->>U: Show Login Form
U->>A: Submit credentials
alt MFA Enabled
A->>U: Show MFA Challenge
U->>A: Submit TOTP code
end
A->>DB: Validate & Create Session
A->>C: Redirect with auth code
C->>A: POST /oauth/token<br/>(code, PKCE verifier)
A->>A: Validate PKCE
A->>C: Return tokens<br/>(access_token, refresh_token, id_token)
C->>A: GET /api/resource<br/>(Bearer token)
A->>C: Protected resource 5. Webhook System¶
Real-time event notifications for integrating with your systems:
graph LR
subgraph "AuthVital"
Event[Event Triggered]
Queue[Event Queue]
Deliver[Delivery System]
end
subgraph "Your App"
Endpoint[Webhook Endpoint]
Handler[Event Handler]
DB[(Your Database)]
end
Event --> Queue
Queue --> Deliver
Deliver -->|POST + HMAC| Endpoint
Endpoint --> Handler
Handler --> DB Event Categories: - subject.* - User lifecycle (created, updated, deleted) - member.* - Membership changes (joined, left, role_changed) - invite.* - Invitation lifecycle - license.* - License assignments - app_access.* - Application access changes
Directory Structure¶
authvital/
├── backend/ # NestJS API Server
│ ├── src/
│ │ ├── auth/ # Authentication (login, register, MFA)
│ │ ├── oauth/ # OAuth 2.0/OIDC endpoints
│ │ ├── tenants/ # Tenant & membership management
│ │ ├── licensing/ # License pool system
│ │ ├── authorization/ # RBAC engine
│ │ ├── sso/ # SSO providers (Google, Microsoft)
│ │ ├── webhooks/ # System webhook delivery
│ │ ├── super-admin/ # Instance administration
│ │ └── prisma/ # Database service
│ ├── prisma/
│ │ ├── schema.prisma # Data model (53KB!)
│ │ └── migrations/ # Database migrations
│ └── sdk/ # @authvital/sdk package
│ └── src/
│ ├── client/ # React SDK
│ ├── server/ # Node.js SDK
│ ├── sync/ # User sync utilities
│ └── webhooks/ # Webhook handlers
├── frontend/ # React Admin Panel
│ └── src/
│ ├── pages/
│ │ ├── admin/ # Super admin UI
│ │ ├── auth/ # Auth flows UI
│ │ └── tenant/ # Tenant admin UI
│ └── components/
└── docker-compose.yml # Local development
Security Architecture¶
Token Security¶
| Token Type | Lifetime | Storage | Purpose |
|---|---|---|---|
| Access Token | 1 hour | Memory | API authorization |
| Refresh Token | 7 days | HttpOnly cookie | Token renewal |
| ID Token | 1 hour | Memory | User identity (OIDC) |
| Auth Code | 10 min | Server only | OAuth exchange |
Key Management¶
- JWT Signing Keys: Ed25519 key pairs, automatically rotated every 7 days
- Master Secret (
MASTER_SECRETenv var): Root-of-trust key that encrypts the Ed25519 private keys at rest in the database, derives HMAC keys for cookies/CSRF/auth codes, and encrypts sensitive data like OAuth client secrets - JWKS Endpoint: Public keys available at
/.well-known/jwks.json— clients validate JWTs against these - Two-Layer Architecture: JWTs are signed by the rotating Ed25519 keys, NOT by the master secret directly. Changing
MASTER_SECRETinvalidates everything because the stored signing keys can no longer be decrypted
MFA Implementation¶
graph TD
Login[Login Request] --> Check{MFA Enabled?}
Check -->|No| Token[Issue Tokens]
Check -->|Yes| Challenge[Return MFA Challenge]
Challenge --> TOTP[User enters TOTP]
TOTP --> Verify{Valid?}
Verify -->|Yes| Token
Verify -->|No| Retry[Retry or Backup Code]
Retry --> TOTP Scalability Considerations¶
Stateless Design¶
- JWT tokens are self-contained (no session lookup)
- Horizontal scaling supported
- Database is the only stateful component
Caching Points¶
| Data | Cache Strategy |
|---|---|
| JWKS | Client-side caching (Cache-Control) |
| User Sessions | Database with indexes |
| Tenant Config | Application-level cache |
Database Indexes¶
Key indexes for performance: - users.email - Login lookups - sessions.token - Session validation - refresh_tokens.id - Token ghosting - memberships(user_id, tenant_id) - Membership checks
Integration Patterns¶
Pattern 1: Full SDK Integration¶
Best for new applications:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ React App │────▶│ Your API │────▶│ AuthVital │
│ (SDK/Client)│ │ (SDK/Server)│ │ │
└─────────────┘ └─────────────┘ └─────────────┘
Pattern 2: Direct OAuth¶
For custom implementations:
┌─────────────┐ ┌─────────────┐
│ Any Client │────▶│ AuthVital │
│ (OAuth lib) │ │ OAuth API │
└─────────────┘ └─────────────┘
Pattern 3: Webhook Sync¶
For keeping local user data:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ AuthVital │────▶│ Your API │────▶│ Your DB │
│ (Webhooks) │ │ (Handler) │ │ (Users) │
└─────────────┘ └─────────────┘ └─────────────┘