Identity & Access Management

Enterprise SSO Implementation

Duration: ~15 hours Date: February 2026 Status: Production
TL;DR

Set up a single sign-on system so I only need one password to access all my homelab applications. Instead of managing 8 different passwords, I log in once and everything just works. The system checks Active Directory (like what companies use for employee logins), then lets me through to whichever app I'm trying to use.

Key Achievement: 8+ applications protected with centralized SSO. Zero password sprawl. 5-minute onboarding for new apps.

The Problem

What I Started With

Why This Sucks

Real-World Example: This is the same problem companies have with SaaS apps. Without SSO, employees have 20+ different passwords for Salesforce, Jira, Slack, etc. That's why enterprise IT implements SSO - and that's what I learned to do here.

The Solution

How It Works (The Simple Version)

Think of it like a security checkpoint at an airport:

You → Security Gate → Plane

If you have a boarding pass (session cookie):
  Security waves you through to your gate

If you don't have a boarding pass:
  Security redirects you to check-in
  → You show your ID (Active Directory login)
  → Get boarding pass (session cookie)
  → Now you can access all gates (apps)
                

What Actually Happens Behind the Scenes

First Time Visiting an App:

  1. You type in the URL: https://docs.homelab.local
  2. Reverse proxy (like a security guard) stops you: "Show me your session cookie"
  3. You don't have one yet, so it redirects you to the login page
  4. You enter your username/password (which gets checked against Active Directory)
  5. Login works → You get a session cookie → Redirected back to the app
  6. Now the security guard sees your cookie and lets you through

Every Time After That:

The Tech Stack

What I Actually Built

The Main Pieces

Active Directory (The User Database)

Authentik (The Login System)

Nginx Proxy Manager (The Security Gate)

Docker (How It All Runs)

Key Technical Decisions

Why Forward Auth vs Native OIDC/SAML
  • Forward auth works with any HTTP(S) application (no app-level changes needed)
  • Application never sees credentials (security)
  • Centralized at network edge (defense in depth)
  • Single pattern scales to unlimited apps
  • Trade-off: Double authentication if app has native auth (acceptable in homelab)
Why Separate Authentik Outpost
  • Performance isolation (auth validation vs login flows, LDAP queries, UI)
  • Separation of concerns (auth validation vs identity management)
  • Mirrors enterprise IdP architecture (e.g., Okta agents)

The Challenges

Challenge 1: Wrong Username Format for LDAP

What Went Wrong:

Error: LDAP bind failed - Invalid credentials

The Problem:

  • I was using email format: admin@domain.local
  • LDAP doesn't understand email format - it needs a specific path
  • Required format: CN=Admin,OU=Users,DC=domain,DC=local

The Fix:

Used the full Distinguished Name (DN) path instead of email/UPN format.

Lesson Learned:

LDAP has its own addressing format. Email-style usernames won't work for bind operations.

Challenge 2: nginx auth_request Returns Wrong Status

What Went Wrong:

401 Unauthorized (even after successful login)

The Problem:

  • nginx's auth_request only accepts 2xx as "allow"
  • Authentik was returning 401 for "not logged in" (correct)
  • But nginx wasn't properly handling the redirect flow

The Fix:

Configured proper error_page 401 = @authentik handling and set up the redirect location block correctly.

Lesson Learned:

HTTP status codes have specific meanings in auth flows. Need to understand how nginx interprets subrequest responses.

Challenge 3: Session Cookies Not Persisting

What Went Wrong:

Login works, but redirected back to login immediately

The Problem:

  • Cookies have domain restrictions
  • Cookie set for auth.domain.local wasn't being sent to app.domain.local
  • Browser security feature, not a bug

The Fix:

Configured Authentik to set cookies for the parent domain .domain.local so they're sent to all subdomains.

Lesson Learned:

When login involves redirects between subdomains, you have to understand cookie policies. This took reading browser documentation and testing different settings.

Results

  • 8+ applications protected with centralized SSO
  • Zero password sprawl - users authenticate once with AD credentials
  • 5-minute onboarding for new applications (reusable pattern)
  • 100% authentication success rate since deployment
  • All authentication events logged centrally in Authentik

Reusable Pattern

Adding SSO to a new application takes ~5 minutes:

  1. In Authentik: Create Proxy Provider + Application (3 clicks)
  2. In Authentik: Assign application to outpost (1 click)
  3. In NPM: Add auth_request location blocks to proxy host (paste config)
  4. Test: Access app → redirect to login → authenticate → access granted

This pattern has been applied to:

  • Documentation platform (Bookstack)
  • Dashboard (Glance)
  • Web IDE (code-server)
  • Monitoring (Uptime Kuma)
  • Backup tool (Duplicati)

And can protect ANY future HTTP(S) application without modification.

Interview Story (STAR Format)

Situation

"I was managing a homelab with 8 self-hosted applications, each with independent user management. This created password fatigue, security risks from reused credentials, and no centralized access control or audit trail."

Task

"Implement enterprise-grade Single Sign-On that would work across all applications - including those without native SSO support - while maintaining security and providing a foundation for future access policies."

Action

"I implemented forward authentication using Authentik as the identity provider, backed by Active Directory as the user directory. The architecture places authentication at the reverse proxy layer, so every HTTP request is validated before reaching the application. This required:

  • Setting up a 2-DC Active Directory environment with LDAP
  • Deploying Authentik with a distributed architecture (main server + outpost)
  • Configuring nginx to intercept requests and validate sessions via subrequests
  • Troubleshooting LDAP bind failures (DN vs UPN format issue)
  • Debugging nginx auth_request status code handling
  • Resolving session cookie propagation through proxy layers

The key technical challenges were understanding LDAP protocol requirements, nginx's auth_request model, and HTTP cookie flow through multi-layer proxies."

Result

"Successfully implemented SSO protecting 8 applications with a reusable pattern that takes ~5 minutes to apply to new apps. Eliminated password sprawl, centralized authentication logging, and built a foundation for future enhancements like MFA and group-based access policies. The implementation mirrors enterprise patterns used by companies like Cloudflare Access or Okta + reverse proxy combinations."

Skills Demonstrated

Enterprise Identity Architecture

LDAP Protocol Active Directory Modern IdP Patterns Forward Auth OAuth2/OIDC Concepts Distributed Systems

Reverse Proxy Engineering

nginx auth_request HTTP Status Handling Header Manipulation TLS/SSL Cookie Management

Systematic Troubleshooting

Log Analysis Protocol Debugging Root Cause Analysis Documentation

What's Next

Immediate Improvements

Future Exploration