Sso Identity

SSO & Identity Management

Centralized authentication and authorization for all web services using Kanidm and OAuth2 Proxy.

Overview

This repository uses Kanidm as the core identity provider. It supports modern authentication standards like WebAuthn (YubiKey), OIDC, and LDAP. To protect web services that don’t natively support OIDC, we use the Forward Auth pattern with OAuth2 Proxy.

Key Components

  1. Kanidm (modules/services/auth/kanidm.nix): The “Source of Truth” for users, groups, and credentials.
  2. OAuth2 Proxy (modules/services/auth/oauth2-proxy.nix): A gateway that handles the OIDC login flow with Kanidm.
  3. Nginx (modules/services/web/nginx.nix): Uses auth_request to intercept requests and verify authentication with OAuth2 Proxy before allowing access to backend services.

Deployment Logic

Where does it run?

  • Kanidm: Typically runs on a stable, persistent node like lab-matrix or bio-alpha. It is exposed to the internet via the VPS (vps-pacman) using our standard Nginx reverse proxy.
  • OAuth2 Proxy: Runs on the same node as Nginx (usually the VPS) to provide fast authentication checks.

Traffic Path

  1. User Request: https://git.alienzj.org -> Hits VPS Nginx.
  2. Intercept: Nginx asks OAuth2 Proxy: “Is this user logged in?”.
  3. Redirect: If no, the user is sent to https://id.alienzj.org (Kanidm) to login with their password and YubiKey.
  4. Authorize: After login, Kanidm sends the user back to OAuth2 Proxy, which sets a secure cookie for .alienzj.org.
  5. Access: Nginx now sees the user is authenticated and proxies the traffic to the Homelab Backend over Tailscale.

Usage: Protecting a Service

To protect any web service with Kanidm SSO, simply set kanidm.enable = true in its module configuration.

Example: Protecting Glance

modules.services.web.glance = {
  enable = true;
  kanidm.enable = true; # This activates the Nginx 'auth_request' protection
};

Supported Services

Currently, the following services have integrated SSO support:

  • Glance (Dashboard)
  • HedgeDoc (Markdown Editor)
  • Linkwarden (Bookmarks)
  • Discourse (Forum)
  • FreshRSS (RSS Reader)
  • Grocy (ERP)
  • Affine (Knowledge Base)
  • Forgejo (Git)
  • Vaultwarden (Password Manager)
  • Stirling-PDF (PDF Tools)

Note: Services like Forgejo and Nextcloud often have native OIDC support, which is preferred for better user mapping if supported.


Frequently Asked Questions

Can services work without SSO?

Yes. If kanidm.enable = false (the default), the service will use its own internal login system. You can always reach your services directly via Tailscale IPs if the SSO system is down.

Why use SSO?

  1. Security: Enforce Hardware MFA (YubiKey) across every single application.
  2. Convenience: Login once, access everything.
  3. Centralization: Disable one user in Kanidm, and they lose access to every service instantly.

How to configure a new OAuth2 Client in Kanidm?

The oauth2-proxy-env secret is a secure environment file that oauth2-proxy uses to authenticate with Kanidm.

OAuth2 Proxy needs a random string to encrypt its session cookies. Run this command to generate one:

python3 -c 'import os,base64; print(base64.urlsafe_b64encode(os.urandom(32)).decode())'

2. Register OAuth2 Proxy in Kanidm

On the machine running Kanidm (e.g., lab-matrix), create the OIDC client:

kanidm oidc create oauth2_proxy "OAuth2 Proxy" https://auth.alienzj.org/oauth2/callback

This command will output a Client ID and a Client Secret.

3. Create the Encrypted Secret File

On your development machine, create the secret using agenix:

agenix -e secrets/oauth2-proxy-env.age

Paste the following into the file (replacing the values):

OAUTH2_PROXY_CLIENT_ID=<your-kanidm-client-id>
OAUTH2_PROXY_CLIENT_SECRET=<your-kanidm-client-secret>
OAUTH2_PROXY_COOKIE_SECRET=<your-generated-cookie-secret>

4. Map the Secret in Nix

Ensure your host configuration (e.g., hosts/vps-pacman/modules/secrets.nix) points to the encrypted file:

age.secrets.oauth2-proxy-env.file = ../../secrets/oauth2-proxy-env.age;