Skip to main content

Command Palette

Search for a command to run...

Architecture Overview of my implemented Web App Authentication System

A high-level walkthrough of how the CSL web app authenticates users through a hybrid IdP + server-session design

Updated
8 min read
Architecture Overview of my implemented Web App Authentication System

Series: Web Authentication Demystified — From Concepts to Real-World
ARC 2 — APPLYING THE THEORY: MY REAL IMPLEMENTATION
Previous: Sessions vs Token-Based Authentication
Next: Deep Dive: The User Authentication Flow in my implemented Web App

Modern authentication systems rarely follow a single pattern. Real applications mix protocols, session models, and infrastructure choices based on constraints that textbooks usually ignore—legacy dependencies, security requirements, user experience goals, and platform limitations.

This article presents the high-level architecture of my real authentication system, built around a HumHub/Yii web application, a government-operated IdP, Redis-backed sessions, and CloudFront signed cookies. We’ll walk through what each component does, how requests flow through the system, and why this design ultimately forms a hybrid authentication model that blends OIDC with traditional server sessions.A high-level walkthrough of how the CSL web app authenticates users through a hybrid IdP + server-session design—and how each component fits into the bigger picture.

Disclaimer

The articles from this arc onward are based on a real authentication system I integrated and implemented for a government education department. Due to the Non-Disclosure Agreement (NDA) between myself and the client, certain internal details, configurations, and architectural specifics have been intentionally generalized or omitted. All explanations focus on the conceptual and technical patterns rather than sensitive operational information. I’ve made every effort to describe the system as accurately as possible while fully respecting confidentiality and security requirements.


Use Case: Enabling Teachers to Access a Third-Party Education Platform Securely

To understand the architecture in a real context, imagine the following scenario—slightly generalized for confidentiality but representative of the actual system design.

A public-sector education department provides every teacher with a centralized government-issued digital identity. This identity is used across multiple official platforms and must also authenticate securely into approved third-party applications, such as the CSL learning platform built with HumHub/Yii.

The challenge is to integrate:

  • A government-operated Identity Provider (IdP) with strict security and reliability requirements

  • A third-party web application with its own authorization logic and user model

  • Existing infrastructure such as Redis sessions, CloudFront delivery, and HumHub’s built-in authentication components

  • A smooth user experience where teachers can sign in once and access what they need without friction

Below is how this use case plays out at a high level.

User Story: A Teacher Logging Into the CSL App

A teacher (let’s call her Ms. Linh) wants to log in to the CSL platform to access teaching materials and administrative tools.

1. She opens the CSL web application

The system checks whether she already has an active session.
If not, CSL redirects her to authenticate using her official government identity.

2. She signs in via the government IdP

Ms. Linh enters her credentials on the government login page—never inside CSL.
The IdP verifies her identity using government-grade authentication and MFA.

3. The IdP returns an authorization code to CSL

CSL exchanges this code for tokens (access token, optional ID token).
These tokens confirm that Ms. Linh is a legitimate teacher authorized by the department.

4. CSL creates its own internal session

Instead of storing tokens in the browser, CSL maps the incoming identity to a local user record and creates a Redis-backed PHP session.
The browser receives only a session cookie.

5. Additional content is served using CloudFront protected by signed cookies

Once authenticated, CSL issues CloudFront signed cookies so Ms. Linh can access protected static assets.

Why This Use Case Matters

This scenario demonstrates why the system cannot simply rely on “pure OIDC” patterns. The application must:

  • integrate with an external identity authority

  • maintain internal user roles, permissions, and workflows

  • ensure tight security around government identities

  • work within existing HumHub/Yii architecture

  • avoid exposing tokens to the browser

  • provide instant, centralized logout capability

  • serve protected assets via CloudFront

These constraints naturally lead to a hybrid authentication flow, where OIDC validates identity but the application maintains its own server-side session that governs how a teacher interacts with CSL.


System Architecture: The Big Picture

My authentication pipeline revolves around several key components:

🔹 1. HumHub/Yii Web Application (CSL Module)

This is the core application the teacher wants to access.
It handles routing, permissions, user interface, and acts as the “client” in the OAuth2/OIDC relationship with the external IdP.

🔹 2. Redis

Used as the shared session store.
HumHub stores authenticated session data here, indexed by the browser’s PHPSESSID cookie.

🔹 3. Government IdP (Identity Provider)

This is where the actual user authentication happens.
The IdP performs login, MFA, issues access tokens, and validates the teacher’s identity.

🔹 4. Database (User & Auth Records)

Stores long-lived user metadata:

  • Local user profile

  • Linking between IdP sub and CSL user_id

  • Status (enabled/disabled)

This ensures my app knows how to map an external user to an internal account.

🔹 5. CloudFront (Signed Cookies)

Used to secure static resource delivery after authenticated login.
Once authenticated, CloudFront cookies allow the browser to access static content that would otherwise be restricted.


Walking Through the Authentication Flow

The following walkthrough mirrors my actual system diagram and real behavior. The diagram below is just a glorified version of my boring UML diagram.

1. User Visits the CSL Page

The browser sends the initial request to the CSL application.

The backend checks:

  • No → User is redirected to /user/auth/login

  • Yes → Proceed to check whether the session exists in Redis

✔ Is there a valid Redis session for this PHPSESSID?

  • No → Redirect to /user/auth/login

  • Yes → Proceed to permission checks

If the session exists and the user has the required permissions, CSL responds with the requested page.

If not, authentication begins.

2. Redirecting to the IdP

The user is redirected to:

/user/auth/external?authclient=idm

This triggers the OAuth2/OIDC Authorization Code Flow with the external IdP.

The browser is sent to the IdP’s /authorize endpoint, where the teacher logs in.

3. IdP Authenticates the User

At this point:

  • The IdP validates credentials (username/password/OTP)

  • If successful, it creates an IdP-side browser session

  • The IdP redirects back to CSL with an authorization code

The backend exchanges the code at the IdP’s /token endpoint.

The IdP returns:

  • access_token

  • (optional) id_token

  • token_type

  • expires_in

4. Backend Validates the User Identity

The CSL backend validates the access token via:

  • Signature (using the IdP’s JWKS keys)

  • iss (issuer)

  • aud (client ID)

  • exp (not expired)

  • sub (unique teacher identity)

Once validated, CSL checks:

✔ Does this teacher already have a user_auth record in the database?

  • No → Create a new internal user auth mapping

  • Yes → Fetch the internal user_id

✔ Is the user status enabled?

If disabled, login is denied.

5. Server Creates Local Session (Hybrid Model)

This is where my system diverges from “textbook” OIDC.

Instead of passing tokens to the browser, the backend:

5.1. Creates a standard server-side session in Redis

  • Stores user ID

  • Stores roles/permissions

  • Stores auth timestamps

  • Stores internal user metadata

(HttpOnly / Secure / SameSite configured)

5.3. Generates CloudFront signed cookies for protected assets

The browser never receives:

  • access tokens

  • ID tokens

  • JWTs of any kind

This dramatically reduces exposure to attacks such as:

  • token theft via XSS

  • token leakage through browser APIs

  • replay attacks


Why the System Is Hybrid

My system is not using pure OAuth2/OIDC on the frontend.

It uses:

  • OIDC features to authenticate identity with a trusted IdP

  • Traditional server sessions to manage logged-in users internally

  • CloudFront cookies to provide private CDN access

  • Redis to maintain distributed server-side session state

This hybridization is intentional and beneficial because:

✔ The IdP handles identity

No password handling in my app.
Strong MFA and identity assurance come “for free.”

✔ The app handles session state

You maintain full control over:

  • permissions

  • role changes

  • user disabling

  • logout

  • session expiration

  • access to internal features

✔ Tokens never leave the backend

A huge security win.


Strengths of This Architecture

1. Strong Separation of Concerns

The IdP manages identity.
The app manages sessions and authorization.

2. High Security

No tokens stored in the browser.
Sessions are HttpOnly and stored in Redis.

3. Immediate Revocation

Deleting the Redis session logs the user out everywhere.

4. MFA and Identity Assurance Provided by IdP

Government IdP guarantees consistent identity checks.

5. Scalable

Redis-backed sessions allow horizontal scaling of application servers.

6. Works with HumHub’s existing session model

No invasive rewrites to Yii/HumHub internals required.


Where the System Deviates From Textbook OIDC

❌ Tokens are not stored client-side

Standard SPAs would store access tokens in memory or cookies.

❌ No use of OIDC UserInfo endpoint in the browser

All profile synchronization happens server-side.

❌ No front-channel ID tokens

My frontend does not parse or validate JWTs.

❌ Session is authoritative, not the JWT

In textbook OIDC systems, the JWT is the session.

❌ Logout is handled by the server session, not IdP logout

My backend decides when the user is logged out—no federated logout.

These deviations are deliberate and appropriate for a secure enterprise/government integration.


Final Thoughts

My authentication system is an example of a practical, real-world architecture that blends modern identity protocols with traditional server sessions to achieve:

  • better security

  • safer token handling

  • clean backend control

  • compatibility with HumHub/Yii

  • strong integration with a government IdP

It’s not “pure” OAuth2 or pure OIDC—and that’s the point.
Real systems adapt patterns to context.

This hybrid architecture offers the best of both worlds:
secure external identity + safe, manageable internal session logic.

And now that we’ve explored the architecture from a high level, the next step is to walk through the entire authentication journey request by request. In the next article, we’ll take a deep dive into the real login flow—how the browser, the CSL web app, Redis, the IdP, and CloudFront all interact to authenticate a user securely in this hybrid system.

Web Authentication Demystified — From Concepts to Real-World

Part 8 of 14

This series breaks down modern web authentication, from core concepts like OAuth, OIDC, and tokens to real implementation details. You’ll learn how the pieces fit together and see how a production-ready system is built and secured.

Up next

Sessions vs Token-Based Authentication

A practical look at how stateful sessions, stateless tokens, and hybrid models work—and how they shape real-world authentication.