Please hold on for a moment while the content loads.
Please hold on for a moment while the content loads.
Multi-Tenant Identity Provider
A production-oriented OpenID Connect identity provider with multi-tenant isolation, TOTP-based MFA, device limit enforcement, and defense-in-depth security. Complete, awaiting production release.
A custom identity provider implementing the OpenID Connect protocol to serve as the centralized authentication layer for an educational platform ecosystem. The system supports tenant-scoped users, projects, OIDC clients, and signing keys, TOTP-based multi-factor authentication, configurable device limits, Redis-backed sessions, and audit-event storage behind a defense-in-depth security middleware chain. The Go IDP and Nuxt administration dashboard are complete and awaiting production release.
Owned design and implementation of the custom Go layer on top of ZITADEL: SSR UI, per-tenant configuration, and integration logic the OIDC interface doesn't expose.
Designed the security controls not available through standard OIDC: MFA enrollment flows, per-user device limits, CSP nonce injection, rate limiting, ReCAPTCHA, and CSRF protection.
Coordinated implementation and reviewed the work of two mid-level engineers. Made collaborative architecture decisions under senior engineer authority.
Built the Nuxt 3 dashboard surface for OIDC-authenticated management of tenants, projects, applications, users, and MFA configuration.
Added 10 Cypress suites across auth and management flows, plus Docker and GitHub Actions workflows for pre-production release validation.
Implemented tenant-scoped queries and composite constraints to reinforce isolation at both application and persistence boundaries.
System architecture showing security middleware chain, authentication layer, and OIDC identity provider
TOTP-based multi-factor authentication sequence with challenge-response and audit logging
Full OIDC implementation with authorization code flow, PKCE, refresh tokens, token introspection, and JWKS endpoint.
Three-level hierarchy (tenant, project, client) with database-level isolation via composite unique constraints.
TOTP-based MFA with QR code provisioning, enrollment flows, and per-user enable/disable controls.
Configurable concurrent session limits per user with device management and remote logout capabilities.
CSP nonces, CSRF tokens, rate limiting, CAPTCHA, input sanitization, HSTS, and session security headers.
Columnar database for high-volume authentication event analytics with batch inserts and structured metadata.
Nuxt 3 dashboard authenticated through OIDC for managing tenants, projects, applications, users, and MFA configuration.
Token validation happens on every authenticated request and requires sub-millisecond latency. Tokens also need natural TTL support and atomic revocation operations.
Redis provides O(1) lookups, native TTL expiry, and pipeline operations for atomic multi-key operations. The token access pattern (frequent reads, infrequent writes) aligns perfectly with Redis strengths.
The OIDC protocol is complex with requirements for PKCE, JWKS rotation, token exchange, and introspection. Implementing from scratch introduces security risk.
Built on a battle-tested OIDC library, reducing protocol implementation risk while allowing customization for business-specific requirements like custom scopes and multi-tenant flows.
Different data types have different access patterns. User profiles need ACID compliance, tokens need low latency, and audit events need analytics-optimized storage.
PostgreSQL for user data (ACID), Redis for tokens (low latency), and a columnar database for audit events (analytics). Each data store is chosen for its workload.
Educational platforms are targets for credential stuffing, session hijacking, and account takeover. No single security measure is sufficient.
Multi-layer middleware chain rejects most malicious requests at the first layer (rate limiting), keeping the system fast for legitimate users.
// Defense-in-depth middleware chain: each layer rejects early.
// Downstream layers never execute if a prior layer fails.
export function createSecurityMiddleware(config: SecurityConfig) {
return compose(
rateLimiter({ windowMs: 60_000, max: 100 }),
cspNonce({ directives: config.cspDirectives }),
csrfProtection({ cookie: true }),
captcha({ score: 0.7, actions: ["login", "register"] }),
inputSanitizer({ maxLength: 1000, allowedTags: [] }),
hsts({ maxAge: 31536000, includeSubDomains: true }),
)
}The platform is built to serve three product tenants (bootcamp, skill-mapper, admin tools). Accidental cross-tenant data leaks would be catastrophic for user trust.
Tenant-scoped queries and composite database constraints reinforce isolation between product tenants and make incorrect associations visible at the persistence boundary.
// Tenant-scoped repository: keep tenant boundaries explicit.
// Every query injects tenantId and relies on composite constraints.
export class TenantScopedRepository<T> {
constructor(
private prisma: PrismaClient,
private model: string,
) {}
async findMany(tenantId: string, where: WhereInput<T>): Promise<T[]> {
return this.prisma[this.model].findMany({
where: { ...where, tenantId },
})
}
async create(tenantId: string, data: CreateInput<T>): Promise<T> {
return this.prisma[this.model].create({
data: { ...data, tenantId },
})
}
}"7 security layers" is a count; this is the reasoning behind it. For each realistic threat against a multi-tenant identity platform, the table lists the concrete mitigation and the layer that owns it.
| Threat | Mitigation | Layer |
|---|---|---|
| Credential stuffing / brute force | Per-IP and per-account rate limiting, progressive delay on repeated failures, lockout after threshold, ReCAPTCHA on login/registration | Edge + App |
| Token theft / replay (XSS-led) | CSP nonce per request (no unsafe-inline), HttpOnly + Secure + SameSite cookies for sessions, short-lived access tokens, PKCE for public clients | App + Session |
| Session fixation / hijack | Session IDs rotated on privilege change, device-limit enforcement, server-side revocation, absolute + sliding expiry | Session |
| Stolen credentials (user-side) | Mandatory TOTP MFA enrollment with 1-step skew tolerance, device-limit per user, audit log of auth attempts | MFA |
| Multi-tenant data leak | Composite unique constraints at DB level (tenant, project, client), tenant scoping in every query, no cross-tenant identifiers in tokens | Data |
| CSRF on state-changing flows | Double-submit cookie CSRF token, SameSite=Lax, origin checks on OAuth redirects | App |
| Audit tampering / secret leakage | Append-only audit log to columnar store, secret auto-redaction before write, retention window | Data |
Authorization code flow with PKCE: the code_verifier binds the token exchange to the original client, defeating interception
Simple implementation, no additional write path
O(n) scan pattern: acceptable at current scale but needs optimization for millions of tokens
Protocol compliance, security, active maintenance, reduced development time
Dependency on external library, upstream API changes, customization constraints
Optimized for time-series queries, columnar storage for aggregations
Additional operational overhead, eventual consistency with primary data
Server-side session control, immediate revocation, no token size limits
Redis dependency for session validation, stateful authentication
Redis Outage (Session Store)
Session validation fails, users cannot authenticate
Redis is an explicit session dependency. The service reports initialization and connection failures rather than silently accepting unverifiable sessions. High-availability failover remains a deployment concern before production release.
ZITADEL Library API Change
OIDC protocol handling may break after upgrade
The dependency is version-pinned in Go modules, with protocol behavior documented through OIDC flow diagrams and server tests. Upgrade validation remains part of release preparation.
Rate Limiter False Positive
Legitimate user blocked after exceeding threshold
The current token-bucket limiter applies bounded per-IP limits to mutating requests. Threshold tuning and operational override policy remain pre-production concerns.
MFA Enrollment Failure
User cannot complete MFA setup, blocked from account
Enrollment validates the TOTP code before marking MFA active, and the profile flow exposes recovery feedback for invalid or failed setup attempts.
Token Revocation Race Condition
Revoked token used briefly before propagation
Server-side Redis session deletion provides immediate control for browser sessions. Exact distributed token-revocation guarantees require production deployment validation.
6 server test suites covering health, login, registration, OTP, password recovery, and profile flows
Go tests exercise HTTP behavior against the running IDP environment and assert response status and rendered auth UI content.
10 suites covering login, registration, OTP, password recovery, profile/MFA, tenant, project, user, application, and health flows
Cypress tests use environment-configured base URLs and credentials, with API setup for tenant, project, and OIDC application lifecycle scenarios.
IDP Docker packaging and Nuxt dashboard build/deployment workflows
Manual release workflow builds and pushes the Go IDP image; staging dashboard changes trigger a Nuxt build and Vercel deployment workflow.
The implementation is complete and packaged for release, but it has not yet been promoted to production. The repository separates the deployable Go IDP and Nuxt dashboard and includes workflows for building the IDP image and deploying the dashboard.
Dockerfile and manual GitHub Actions workflow build and publish a tagged authentication-server image.
Staging dashboard changes run a Nuxt build and deploy workflow targeting Vercel.
Composite unique constraints prevent cross-tenant data access even if application-level checks have bugs.
OIDC is complex. Using a battle-tested library for protocol compliance while customizing business logic separately reduces security risk.
Tokens need low latency (Redis), users need ACID (PostgreSQL), audit events need analytics (columnar database). One size does not fit all.
Most malicious requests are caught by rate limiting before they reach authentication logic. This keeps the system fast for legitimate users.
A deep dive into the TOTP-based multi-factor authentication implementation used in this project.
Read the full gist →The CSP nonce injection middleware that generates per-request cryptographic nonces for inline script/style security.
Read the full gist →The per-IP token bucket rate limiter protecting authentication endpoints from brute force attacks.
Read the full gist →This is a proprietary pre-production system. The details above reflect my actual work. Additional implementation evidence is available upon request:
Contact me to arrange verification under NDA.