Single Sign-On selbst gehostet: Authentik, Keycloak und Cloudflare Access im Vergleich
Du kennst das: Jeder Dienst im eigenen Netz hat eigene Login-Seiten, eigene Passwörter, eigene Benutzerdatenbanken. Ein Mitarbeiter verlässt das Unternehmen — und drei Wochen später findest du noch, dass sein Account auf dem internen Wiki, in der Ticketsystem-Oberfläche und im Monitoring noch aktiv ist. Oder du selbst hast auf vier verschiedenen Selfhosted-Services in verschiedenen Passwörtern gesetzt, weil du sie nicht alle auf einmal ändern wolltest.
Single Sign-On (SSO) löst dieses Problem, indem es einen zentralen Identitätsanbieter (Identity Provider, IdP) einführt, gegen den sich alle Dienste richten. Der User meldet sich einmal an — und die Dienste vertrauen dem IdP, wenn er ihnen sagt: „Das ist diese Person, und sie hat sich erfolgreich authentifiziert."
Warum die meisten Selfhoster trotzdem keine SSO einrichten, ist nicht technische Schwierigkeit allein — es ist, dass die meisten Articles entweder zu theoretisch sind (Prozess-Auth-Flows mit Paint-Strichdiagrammen) oder direkt in eine Enterprise-Wolke laufen. Dieser Artikel befasst sich mit dem, was für kleine Firmen (5–50 Mitarbeiter) und technisch interessierte Homelab-Betreiber tatsächlich umsetzbar ist: drei Kandidaten, ein konkretes Docker-Setup, Realitätscheck im Produktivbetrieb.
Was SSO fachlich löst — und was nicht
SSO löst:
- Einmalige Anmeldung: Der Nutzer authentifiziert sich einmal gegen den IdP. Danach akzeptieren alle am IdP registrierten Services diesen Login ohne weitere Passwortabfrage (Single Sign-On).
- Zentrales Onboarding/Offboarding: Wenn ein Mitarbeiter die Firma verlässt, wird sein IdP-Konto deaktiviert — und er verliert automatisch den Zugang zu allen verbundenen Diensten. Keine manuelle Aufräumarbeit auf fünf verschiedenen App-Servern mehr.
- Auditierbarkeit: Der IdP protokolliert, wann sich wer anmeldet — eine zentrale Logquelle für den Zugang zu internen Diensten. Das hilft bei Fragen wie: „Hat der Ex-Mitarbeiter nach dem Ausscheiden noch was angefasst?"
- Standardisierte Integration: OIDC und SAML sind offene Protokolle. Wenn ein Dienst diese unterstützt, kannst du ihn an deinen IdP anbinden — ohne proprietäre Software von Drittanbietern.
SSO löst nicht:
- Schwache Passwörter: Ein SSO-System macht es nicht besser, wenn die Nutzer generell schwache Passwörter wählen. Der IdP hält die zentrale Zugangsstelle — wenn dort die Authentifizierung schwach ist, ist das ganze System schwach. Hardware-Schlüssel (FIDO2/YubiKey) für den IdP-Login bleiben empfehlenswert, besonders wenn der IdP von außen erreichbar ist.
- Hacking von Datenbanksen, APIs und Service-to-Service-Kommunikation: SSO schützt den Nutzer-Login. Es verschafft dir aber keine Zugangskontrolle für Backend-Dienste, die sich untereinander authentifizieren (z.B. Datenbank-Zugänge, API-Keys zwischen Services). Das ist ein eigenes Thema.
- Verschlüsselung von Daten im Transit oder im Ruhezustand: SSO handelt Authentifizierung und Authorisierung. Es verschafft dir kein TLS, kein Verschlüsselungsmanagement. Das bleibt Aufgabe des Reverse-Proxy und der Individual-Dienste.
- Device-Trust: Wenn ein Gerät gestohlen wird und der IdP-Login mit Passwort + 2FA möglich ist, kann der Dieb sich anmelden. SSO löst nicht das Device-Trust-Problem.
Die drei Kandidaten im Überblick
Für den Anwendungsfall "kleine Firma oder Fortgeschrittener Homelab" kommen drei Lösungen infrage. Die Auswahl fällt nicht nach Feature-Listen, sondern nach den tatsächlichen Bedingungen — wie viele Services müssen verbunden werden, welche Protokolle unterstützen die Dienste OIDC oder SAML, wie viel Wartungsaufwand ist akzeptabel.
| Kriterium | Authentik | Keycloak | Cloudflare Access |
|---|---|---|---|
| Protokolle | OIDC (primär), SAML (über Brokern oder Flow-Editor), LDAP-Integration als Benutzerverzeichnis-Backend | OIDC, SAML (vollständig, inkl. Identity-Brokering), OpenID Connect Dynamic Client Registration | OIDC (für Dienste hinter Access geschützte Web-Applikationen), Cloudflare-eigenes Access-Protokoll fürZTNA; SAML nur in Enterprise-Plänen |
| Benutzerverzeichnis | Eigene Benutzerdatenbank (integriert), LDAP/Active Directory als Backend, SAML-IdP-Brokering | Eigene Benutzerdatenbank, LDAP/AD, Identity-Brokering (andere IdPs als Upstream) | Cloudflare-eigene Identitätsquellen (Email, SSO mit SAML/OIDC von externen IdPs wie Google, Azure AD, Okta); kein eigenes Benutzerdatenbank-Modell |
| Lizenzkosten | Open Source (MIT), keine Server-Lizenzen. Cloudflare-übertragene Zugriffsschicht nicht enthalten. | Open Source (Apache 2.0) — Keycloak selbst kostenlos. Red Hat entwickelt Keycloak als Open-Source-Projekt weiter; einige Enterprise-Features (z.B. erweiterte Reporting, bestimmte Automatisierungen) können künftig in kommerziellen Varianten landen | Free-Plan (bis zu 50 Nutzer, begrenzte ZTNA-Funktionen), danach ab ~3 €/Nutzer/Monat für Paid-Pläne. Keine eigene Server-Infrastruktur nötig. |
| Hardwarebedarf | Mindestens 2 CPU-Kerne, 2 GB RAM für den produktiven Betrieb (PostgreSQL + Authentik-App + Worker). Für kleine Homelab auf einem 4-Core-System mit 8 GB RAM machbar. | Mindestens 2 GB RAM für den Keycloak-Server, 4 GB empfohlen für Produktivumgebungen mit vielenRealm-Entrypoints. Java-Laufzeitumgebung braucht Overhead. Günstig auf einem dedizierten Rechner mit 4+ GB freiem RAM. | Kein eigener Server — Cloudflare-infrastruktur. Client-Seite ein Cloudflare-Tunnel (cloudflared) oder ein Access-Gateway, das auf dem eigenen Netz läuft; das ist ressourcenschonend (ein paar MB RAM, kein spezialisiertes Hardware). |
| Bedienaufwand | Mittel: OIDC-Client-Konfiguration im Web-UI, aber die Einrichtung ist mit klaren Konzepten (Application → OIDC-Client → Credentials) dokumentiert. Benutzerverwaltung über Web-UI oder API. | Hoch: Keycloak hat ein sehr breites Feature-Set und eine komplexere Oberfläche. Realms, Clients, Roles, Groups, Identity-Brokering, User-Federation — das Konzeptmodell ist mächtig, aber die Einarbeitung dauert. Für einfache OIDC-Integration reicht der Funnel aber. | Niedrig: Einrichtung über das Cloudflare-Dashboard. Der Access-Policy-Generator ist GUI-getrieben, keine Serverwartung. Aber: Abhängigkeit von Cloudflare, Domain muss bei Cloudflare eingetragen sein. |
| Eignung für Firmen | Gut für Firmen, die volle Eigenkontrolle über ihre Identitätsdaten und -protokolle wollen und bereit sind, den IdP selbst zu betreiben. OIDC-Integration läuft in jeder modernen Webframework gut. SAML über Flow-Editor erreichbar, aber zusätzlicher Aufwand. | Gut für Firmen mit komplexeren Anforderungen (mehrere Realms für Sub-Marken/Bereiche, Identity-Brokering zu externen IdPs, SAML-schwergewichtige Legacy-Anwendungen, erweiterte Rollen-Engine). Höhere Einrichtungskosten, höhere Flexibilität. | Gut für Firmen, die keine eigene IdP-Server-Infrastruktur betreiben wollen und die Domain bereits bei Cloudflare haben. Cloudflare Access als Identity-Aware Proxy ist eine pragmatische Wahl für Web-Dienste, weniger für Machine-to-Machine-Integrationen. |
Abgrenzung zu den anderen BsN-Artikeln
Dieser Artikel behandelt nur die Authentifizierungsschicht — wer darf auf welchen Dienst zugreifen und wie wird diese Frage zentral entschieden. Die Artikel sicherer-fernzugriff.md (Tailscale, WireGuard) und docker-vs-vm.md behandeln andere Schichten:
- sicherer-fernzugriff.md betrachtet, wie man Dienste Netzwerk-seitig erreichbar macht (Tailscale als Overlay-Netzwerk, WireGuard als VPN, Reverse-Tunnel). Mit SSO hast du eine Authentifizierung hinter dem Dienst — aber den Netzwerk-Zugang dazu regelt der Fernzugriff-Artikel einzeln. Die beiden Konzepte sind komplementär: Ein Dienst kann über Tailscale erreichbar gemacht sein und zusätzlich SSO-geschützt werden, oder ein Dienst kann nur lokal erreichbar sein und SSO als "wer darf hier hingehen"-Mechanismus nutzen.
- docker-vs-vm.md betrachtet die Virtualisierungsebene: Container oder VM für einen Dienst. Authentik läuft typischerweise als Docker-Container (oder als VM, wenn man es anders betreiben will). Die Entscheidung dort ist eine Infrastruktur-Entscheidung; die SSO-Anbindung ist eine Anwendungskonfiguration. Der vorliegende Artikel setzt voraus, dass du Docker verwendest — eine Nicht-Docker-Alternative steht im FAQ-Block.
Vollständige Authentik-Anleitung mit OIDC
Authentik ist der Kandidat mit dem günstigsten Einstieg: Docker-basiert, Web-UI klar strukturiert, OIDC-default, keine Java-Laufzeitumgebung. Die folgende Anleitung richtet ein minimales, produktionsnahes Authentik-Setup ein und verbindet ein Beispiel-Python-Service als OIDC-Client.
Voraussetzungen
- Ein Linux-Server mit Docker und Docker Compose (Debian, Ubuntu oder ähnlicher Distribution)
- Ein Reverse-Proxy vor Authentik, der TLS-Terminierung übernimmt (Caddy, Nginx, Traefik — in diesem Beispiel Caddy, weil BsN bereits Caddy in anderen Artikeln dokumentiert)
docker composeVersion 2.x (in den meisten modernen Distributionen alsdocker composeohne Bindestrich verfügbar)
Schritt 1: Das grundlegende docker-compose-Grundgerüst
Erstelle ein Verzeichnis für die Authentik-Instanz:
mkdir -p ~/authentik/{data,media}
cd ~/authentik
Erstelle docker-compose.yml mit den folgenden Inhalten. Das Setup besteht aus drei Diensten: PostgreSQL als Datenbank, Redis als Caching/Session-Backend, und Authentik selbst.
version: "3.8"
services:
# PostgreSQL-Datenbank für Authentik
postgres:
image: docker.io/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U authentik"]
interval: 10s
timeout: 5s
retries: 3
environment:
POSTGRES_USER: authentik
POSTGRES_PASSWORD: ${PG_PASSWORD}
POSTGRES_DB: authentik
volumes:
- ./data/postgres:/var/lib/postgresql/data
networks:
- authentik-net
# Redis für Caching und Session-Speicherung
redis:
image: docker.io/redis:7-alpine
restart: unless-stopped
command: redis-server --save "" --appendonly "no"
networks:
- authentik-net
# Authentik-Applikation
authentik:
image: docker.io/authentik/authentik:latest
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
environment:
# Datenbank-Verbindung — die Werte kommen aus der .env-Datei (siehe Schritt 2)
AUTHENTIK_DB_HOST: postgres
AUTHENTIK_DB_USER: authentik
AUTHENTIK_DB_PASSWORD: ${PG_PASSWORD}
AUTHENTIK_DB_NAME: authentik
AUTHENTIK_REDIS__HOST: redis
# URL unter der Authentik erreichbar ist — hier über den Reverse-Proxy mit TLS
AUTHENTIK_URL: https://auth.brillianze.de
# Secret für Session-Cookies und interne Verschlüsselung — zufälliger Wert,}|=32 Zeichen
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET}
# Admin-Konto: Name, E-Mail, Passwort werden bei erster Initialisierung erstellt
# Das wird im nächsten Schritt über ein CLI-Kommando gesetzt
volumes:
- ./media:/media
- ./data:/data
networks:
- authentik-net
networks:
authentik-net:
driver: bridge
Erstelle eine .env-Datei im selben Verzeichnis mit den konkreten Werten (Passwörter und Secrets nie in Version Control):
# PostgreSQL-Passwort für den authentik-DB-Benutzer
PG_PASSWORD=$(openssl rand -hex 24)
# Authentik internes Secret Key (für Cookie-Verschlüsselung, JWT-Signierung)
AUTHENTIK_SECRET=$(openssl rand -hex 32)
# Diese beiden Variablen schreiben wir in .env, damit docker compose sie liest
echo "PG_PASSWORD=$PG_PASSWORD" > .env
echo "AUTHENTIK_SECRET=$AUTHENTIK_SECRET" >> .env
Anmerkung: In einer produktiven Umgebung solltest du diese Werte in einem Secrets-Manager oder zumindest in einer passwortgeschützten Datei ablegen. Die .env-Datei gehört nicht ins Git-Repository der Homelab-Konfiguration.
Starte die Infrastruktur:
docker compose up -d
Warte, bis die PostgreSQL-Instanz gesund ist (das depends_on mit condition: service_healthy sorgt dafür, dass Authentik nicht vor der Datenbank startet):
docker compose logs -f postgres
Sobald du database system is ready to accept connections siehst, kannst du das Frontend überwachen:
docker compose logs -f authentik
Schritt 2: Admin-Benutzer einrichten
Authentik bringt nach dem ersten Start keine vordefinierten Benutzer mit. Du erstellst den ersten Admin-Benutzer über die Authentik-Kommandozeilen-Schnittstelle (CLI) im Container:
# Container-Name "authentik-authentik-1" entsteht aus dem Verzeichnisnamen des Compose-Projekts;
# prüfe mit "docker ps" den exakten Namen oder nutze "docker compose exec authentik ..."
docker compose exec authentik authentik createuser \
--username admin \
--email bsndemo@brillianze.de \
--password "EinSehrStarkesPasswortDasNieWiederholtWird" \
--is-superuser \
--autocomplete
Hinweis: Das --autocomplete-Flag sagt Authentik, den Benutzer sofort zu aktivieren und das Passwort im Klartext nicht wieder zu speichern (es wird gehasht). In der Produktionsumgebung wählst du ein Passwort, das du in einem Passwort-Manager ablegen — und gibst es nicht in Chat-Protokolle, Terminal-History oder Konfigurationsdateien.
Nach dem Erstellen kannst du dich an der Web-Oberfläche anmelden unter der URL, die du in AUTHENTIK_URL eingetragen hast. Beim ersten Login fragt Authentik ggf. nach einer Verifizierung über E-Mail — das hängt von deinen SMTP-Einstellungen ab (in der Web-Oberfläche unter Einstellungen → Email).
Schritt 3: Einen OIDC-Client anlegen
Ein OIDC-Client repräsentiert den Dienst, der sich gegen Authentik authentifizieren will. Du erstellst ihn in der Web-Oberfläche:
1. Öffne die Authentik-Web-Oberfläche (die AUTHENTIK_URL) und melde dich mit dem Admin-Benutzer an.
2. Gehe zu Anwendungen → OIDC-Client (oder, je nach Version, zu Applications → + Anwendung hinzufügen → OIDC-Client).
3. Erstelle einen neuen Client mit folgenden Eigenschaften:
- Name: Ein interner Bezeichner, z.B. python-beispiel-service
- Client ID: Ein eindeutiger Identifier, z.B. python-exampleservice-oidc
- Client Secret: Authentik generiert einen hier; kopiere ihn — du brauchst ihn später im Python-Service
- Redirect URIs: Die URL, an die Authentik den User nach erfolgreichem Login weiterleiten soll, z.B. https://python-service.brillianze.de/callback
- Grant Types: Mindestens Authorization Code für Web-Applikationen. Refresh Token aktivieren, damit der Service Tokens frisch halten kann, ohne den User immer wieder um Einwilligung zu bitten.
- Response Types: code (Authorization Code Flow — der sichere Standard für Web-Applikationen)
Speichere den Client und notiere dir:
Client ID(öffentlich, aber identifiziert den Client)Client Secret(geheim, nur zwischen Authentik und dem betroffenen Service)Authorization Endpoint:https://auth.brillianze.de/api/v3/providers/oidc/<issuer-id>/authorizeToken Endpoint:https://auth.brillianze.de/api/v3/providers/oidc/<issuer-id>/tokenUserinfo Endpoint:https://auth.brillianze.de/api/v3/providers/oidc/<issuer-id>/userinfo
Die exakten Endpunkt-URLs findest du in der OIDC-Client-Konfiguration oder unter Einstellungen → Identity Providers → OIDC → Endpoints. Die <issuer-id>-Platzhalter müssen durch die reale ID ersetzt werden, die Authentik für den OIDC-Provider vergibt.
Schritt 4: Beispiel-Python-Service mit OIDC schützen
Der Beispiel-Service ist eine minimale Flask-Applikation, die zwei Dinge tut: Sie zeigt eine geschützte Seite, wenn ein gültiger Access-Token vorliegt (der vom IdP ausgestellt wurde), und sie führt den OAuth2-Authorization-Code-Flow aus, um den Token vom Authentik-IdP zu erhalten.
Die Beispiel-App nutzt authlib (Python-Bibliothek für OAuth2/OIDC) in der Version 1.x. Sie führt nicht den eigenen Cryptographic-Priming durch — Authlib kümmert sich um Token-Exchange, State-Parameter, PKCE (wenn aktiviert).
requirements.txt:
Flask==3.1.0
authlib==1.3.2
requests==2.32.3
app.py:
"""
Beispiel-Python-Service mit OIDC gegen Authentik.
Dies ist ein minimales Beispiel — in einer produktiven Applikation
solltest du Sessions sicherer verwalten, HTTPS erzwingen,
Tokens nicht im Klartext loggen und PKCE aktivieren (authentik unterstützt es).
"""
import os
from flask import Flask, redirect, session, url_for, jsonify, request
from authlib.integrations.flask_client import OAuth
app = Flask(__name__)
# Flask-Session Secret — separat vom Authentik Secret Key; eigenes Zufallspasswort
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "bitte-aendern")
# OIDC-Konfiguration aus Umgebungsvariablen — in Produktion durch Konfigurationsmanagement ersetzen
AUTHTIK_BASE_URL = os.environ.get("AUTHTIK_BASE_URL", "https://auth.brillianze.de")
OIDC_CLIENT_ID = os.environ.get("OIDC_CLIENT_ID", "python-exampleservice-oidc")
OIDC_CLIENT_SECRET = os.environ.get("OIDC_CLIENT_SECRET", "")
OIDC_REDIRECT_URI = os.environ.get("OIDC_REDIRECT_URI", "https://python-service.brillianze.de/callback")
# OAuth-Client initialisieren
oauth = OAuth(app)
# Den OIDC-Provider registrieren — Authlib nutzt die Discovery-URL, um
# Authorization-Endpunkt, Token-Endpunkt usw. automatisch zu laden
oauth.register(
name="authentik",
server_metadata_url=f"{AUTHTIK_BASE_URL}/api/v3/providers/oidc/<issuer-id>/.well-known/openid-configuration",
client_id=OIDC_CLIENT_ID,
client_secret=OIDC_CLIENT_SECRET,
access_token_url=f"{AUTHTIK_BASE_URL}/api/v3/providers/oidc/<issuer-id>/token",
authorize_url=f"{AUTHTIK_BASE_URL}/api/v3/providers/oidc/<issuer-id>/authorize",
client_kw={\"token_endpoint_auth_method\": \"client_secret_post\"},
# PKCE aktivieren: authentik unterstützt S256; CSRF-Schutz im Authorization Code Flow
pkce="S256",
)
@app.route("/")
def index():
"""Startseite: Wenn der Benutzer nicht authentifiziert ist, zum Login weiterleiten."""
if "user" not in session:
return redirect(url_for("login"))
return """
<h1>Beispiel-Python-Service — geschützt mit OIDC</h1>
<p>Du bist angemeldet als: <b>{}</b></p>
<p>Access-Token (nicht im Produktivbetrieb im HTML ausgeben!): <code>{}</code></p>
<p><a href="/logout">Abmelden</a></p>
""".format(
session.get("user", {}).get("email", "unbekannt"),
session.get("access_token")[:20] + "..." if session.get("access_token") else "keiner",
)
@app.route("/login")
def login():
"""Authentifizierung starten: Authorization Code Flow an Authentik."""
# Redirect URI muss exakt mit dem in Authentik konfigurierten Redirect URI übereinstimmen
redirect_uri = url_for("callback", _external=True)
return oauth.authentik.authorize_redirect(
redirect_uri=redirect_uri,
scope="openid profile email",
)
@app.route("/callback")
def callback():
"""Authentik hat den User zurückgeleitet und einen Code übergeben — Token austauschen."""
try:
token = oauth.authentik.authorize_access_token()
except Exception as exc:
# In Produktion: detaillierte Fehlerbehandlung, Logging, keine Stack-Traces an Endnutzer
return "Authentifizierungsfehler: {}".format(exc), 401
# Userinfo vom IdP anfordern — enthält claims wie email, name
userinfo = oauth.authentik.userinfo(token=token)
session["user"] = userinfo
session["access_token"] = token.get("access_token", "")
return redirect(url_for("index"))
@app.route("/logout")
def logout():
"""Session löschen — keine Verbindung zum IdP (Local Logout)."""
session.clear()
return redirect(url_for("index"))
if __name__ == "__main__":
# Entwicklung nur: Flask-Built-in-Server über HTTP. In Produktion: WSGI-Server (Gunicorn)
# hinter Reverse Proxy mit TLS
app.run(host="0.0.0.0", port=5000, debug=False)
Wichtige Hinweise zum Beispiel:
<issuer-id>in den URLs muss durch die tatsächliche ID ersetzt werden, die Authentik vergibt. Die OpenID-Connect-Discovery-URL (/.well-known/openid-configuration) ist der Standardweg — Authlib lädt die Metadaten selbst und du kannst nur dieserver_metadata_urleingeben. Das spart, die einzelnen Endpunkte manuell zusammenzusuchen.- Der
scope="openid profile email"definiert, welche Informationen der IdP über den authentifizierten Benutzer zurückgibt.openidist obligatorisch für OIDC;profileundemailsind optional, aber in der Praxis fast immer beantragt. - Den Access-Token nie in Logs, HTML oder Debug-Ausgaben vollständig ausgeben — nur Teile zum Testen, wie im Beispiel gezeigt.
Schritt 5: Den Token-Ausstellungsprozess mit curl testen
Bevor du den Python-Service deployst, ist es sinnvoll, den OAuth2-Authorization-Code-Flow manuell mit curl zu verifizieren. Das hilft, Misskonfigurationen (falsche Redirect URIs, falsche Scopes, falsch generierte Secrets) als solche zu erkennen.
Der Authorization-Code-Flow ist zweistufig:
Schritt A: Den Authorization-Link bauen und im Browser öffnen. Der User meldet sich bei Authentik an und Authorisiert den Client. Authentik leitet zurück an den Redirect URI mit einem code-Parameter.
Der Link (zum manuellen Klick im Browser):
https://auth.brillianze.de/api/v3/providers/oidc/<issuer-id>/authorize?
response_type=code&
client_id=python-exampleservice-oidc&
redirect_uri=https://python-service.brillianze.de/callback&
scope=openid%20profile%20email&
state=<ein-zufaelliger-state-string>
state ist ein zufälliger String, den du erzeugst und der später im Callback validiert wird (CSRF-Schutz). In der manuellen curl-Test-Phase kannst du state=teststate123 verwenden.
Öffne diesen Link in einem Browser, melde dich mit einem Test-Benutzer (nicht zwingend dem Admin) an, und erlaube den Zugriff. Du landest nach erfolgreicher Authorisierung auf:
https://python-service.brillianze.de/callback?code=<authorization-code>&state=teststate123
Kopiere den code-Wert aus der URL.
Schritt B: Den Authorization Code gegen einen Access-Token austauschen:
# Die Werte aus deiner Authentik-Client-Konfiguration einsetzen
CLIENT_ID="python-exampleservice-oidc"
CLIENT_SECRET="<hier-den-Client-Secret-eintragen>"
REDIRECT_URI="https://python-service.brillianze.de/callback"
ISSUER_ID="<die-issuer-id-aus-authentik>"
CODE="<den-code-aus-dem-browser-aufruf-eintragen>"
curl -X POST "https://auth.brillianze.de/api/v3/providers/oidc/${ISSUER_ID}/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=${CODE}" \
-d "redirect_uri=${REDIRECT_URI}" \
-d "client_id=${CLIENT_ID}" \
-d "client_secret=${CLIENT_SECRET}"
Erwartete Response (JSON):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": "openid profile email"
}
Der access_token ist ein JWT (JSON Web Token). Du kannst ihn mit einem JWT-Debugger (offline, lokal — keine Tokens an Online-Debugger schicken) inspizieren, um zu sehen, welche Claims er enthält. Typische Claims in einem Authentik-ID-Token: sub (Subject-ID), email, name, preferred_username, iss (Issuer-URL), aud (Client-ID), exp (Ablaufzeit), iat (Ausgestellt-Zeit).
Validierung des Tokens:
Das JWT ist signiert — Authentik signiert mit einem privaten RSA-Schlüssel, und der öffentliche Schlüssel steht unter der Discovery-URL (jwks_uri). Eine korrekte Validierung würde den öffentlichen Schlüssel laden, die Signatur verifizieren und exp/iss/aud prüfen. Für den Test mit curl reicht es, den Token gegen den Userinfo-Endpunkt zu prüfen:
TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
curl -X GET "https://auth.brillianze.de/api/v3/providers/oidc/<issuer-id>/userinfo" \
-H "Authorization: Bearer ${TOKEN}"
Erwartete Response:
{
"sub": "abcdef123456",
"email": "testuser@brillianze.de",
"email_verified": true,
"name": "Test Benutzer",
"preferred_username": "testuser"
}
Wenn die Userinfo-Antwort kommt und sub + email enthält, ist der Token gültig und die OIDC-Integration korrekt konfiguriert. Der Python-Service kann nun denselben Token vom Authorization Code Flow erhalten und gegen den Userinfo-Endpunkt validieren.
Schritt 6: Den Beispiel-Service als Docker-Container starten
Das docker-compose.yml für den Beispiel-Service (separates Projekt oder als zusätzlicher Dienst):
version: "3.8"
services:
python-beispiel-service:
image: docker.io/python:3.12-slim
restart: unless-stopped
ports:
- "127.0.0.1:5000:5000"
environment:
FLASK_SECRET_KEY: ${FLASK_SECRET}
AUTHTIK_BASE_URL: https://auth.brillianze.de
OIDC_CLIENT_ID: python-exampleservice-oidc
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
OIDC_REDIRECT_URI: https://python-service.brillianze.de/callback
volumes:
- ./app:/app
command: >
bash -c "pip install --no-cache-dir -r /app/requirements.txt &&
gunicorn --bind 0.0.0.0:5000 --workers 2 'app:app'"
networks:
- authentik-net
networks:
authentik-net:
external: true
Beachte: Der Dienst bindet sich nur an 127.0.0.1, nicht an alle Interfaces. Der Reverse-Proxy (Caddy, Nginx) macht ihn nach außen erreichbar — das ist sicherer als eine direkte Port-Exposition.
Produktivbetrieb: Was du nach derEinrichtung brauchst
TLS über den eigenen Reverse Proxy
Authentik führt in der Standardkonfiguration keine TLS-terminierung selbst durch. Die AUTHENTIK_URL ist die URL, unter der es erreichbar sein soll — aber das Traffik von Clients zu Authentik muss verschlüsselt sein, sonst werden die Cookies (Session, OIDC- Tokens im Browser) unverschlüsselt übertragen.
Ein Caddy-Reverse-Proxy in der BsN-Nutzung (vollständigere Konfiguration in einem separaten Artikel "Interne PKI und Caddy für Selfhosted-Dienste"):
auth.brillianze.de {
tls /pfad/zu/zertifikat.crt /pfad/zu/private-key.key
reverse_proxy authentik:80 {
# Forward das X-Forwarded-Proto, damit Authentik weiß, ob die
# Client-Verbindung HTTPS war (wichtig für Cookie-Secure-Flag)
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-For {remote}
}
}
Authentik selbst besitzt eine Konfigurationsoption PROXY_FIX, die vom Reverse Proxy gesendete Header akzeptiert und für interne URL-Berechnung nutzt. In docker-compose.yml kannst du hinzufügen:
environment:
...
AUTHENTIK_PROXY_FIX: "true"
Backups der Konfiguration
Authentik speichert seine Konfiguration (Applications, OIDC-Clients, Policies, Benutzer, Flows) in der PostgreSQL-Datenbank. Die media- und data-Volumes enthalten hochgeladene Bilder (z.B. Logos für Anwendungen) und einige Konfigurationsdateien.
Ein Backup-Skript (via cron täglich, z.B. 03:00 Uhr):
#!/bin/bash
# authentik-backup.sh — vereinfachtes Backup für Authentik-Datenbank und Volumes
# In Produktion: verschlüsseln, nach einem separaten Host übertragen, Retention-Policy
BACKUP_DIR="/var/backups/authentik"
DATE=$(date +%Y-%m-%d)
PG_CONTAINER="authentik-postgres-1"
DATA_DIR="/home/bsn/authentik"
mkdir -p "${BACKUP_DIR}/${DATE}"
# Datenbank-Dump über docker exec — der Dokumenten-User ist "authentik"
docker exec "${PG_CONTAINER}" pg_dump -U authentik authentik | \
gzip > "${BACKUP_DIR}/${DATE}/authentik-db-${DATE}.sql.gz"
# Volumes komprimiert archivieren
tar czf "${BACKUP_DIR}/${DATE}/authentik-media-${DATE}.tar.gz" -C "${DATA_DIR}" media
tar czf "${BACKUP_DIR}/${DATE}/authentik-data-${DATE}.tar.gz" -C "${DATA_DIR}" data
# Alte Backups (älter als 30 Tage) aufräumen
find "${BACKUP_DIR}" -type d -mtime +30 -exec rm -rf {} \;
Das Backup alleine bringt nichts, wenn es nicht getestet wurde — ein Restore-Test (Datenbank in eine Test-Instanz laden, prüfen ob Auth-Flows und Clients funktionieren) sollte mindestens einmal pro Quartal gemacht werden.
Ausfallverhalten wenn der Identity Provider steht
Wenn Authentik (oder der gesamte Server, auf dem es läuft) nicht verfügbar ist, können sich Nutzer nicht mehr anmelden. Was passiert mit bereits angemeldeten Sessions?
- Sessions im Browser: Die Authentik-Session (Cookie) ist zeitlich begrenzt. Wenn die Session abläuft, während der IdP offline ist, kann der Nutzer sich nicht neu anmelden. Die Session-Gültigkeit konfigurierst du in Authentik unter Einstellungen → Sessions.
- Access-Token in Diensten: Ein Access-Token, das der Dienst bereits erhalten hat, ist solange gültig, bis es abläuft (
expires_in). Wenn der Dienst die Token nicht selbst verlängern muss (weil sie länger leben als die geplante IdP-Auszeit), können Nutzer solange weiterarbeiten, bis ihr Access-Token abläuft. - Refresh-Token: Wenn der Dienst den Refresh-Token-Flow nutzt und versucht, ein neues Access-Token zu holen, während der IdP offline ist — der Refresh scheitert. Das ist das Szenario, in dem Nutzer eine Unterbrechung merken.
Praxisempfehlung: Für wenige kritische Dienste (z.B. das Ticketsystem) kannst du die Access-Token-Lebensdauer entsprechend lang bemessen (z.B. 8 Stunden), Refresh-Token ebenfalls, und machst es den Nutzern so gut wie möglich. Für hochkritische Dienste ist ein kluges Fallback (z.B. lokale Fallback-Authentifizierung mit eigenem Benutzernamens-Verzeichnis, das nur im Notbetrieb aktiviert wird) eine Facility, die enterprise-grade IdPs bieten. Authentik hat keine eingebaute "Notfall-Modus"-Funktion — das müsstest du selbst bauen (z.B. eine gesonderte Anwendung ohne OIDC-Client-Integration in der Produktion, aber mit der gleichen Benutzerdatenbank im Hintergrund über den Authentik-API-Schnittstelle oder direkt über die Datenbank).
Passwortrichtlinien
Authentik hat unter Einstellungen → Passwortrichtlinien grundlegende Regeln: Mindestlänge, Komplexitätsanforderungen (Großbuchstaben, Ziffern, Sonderzeichen), Verbotsliste für häufige Passwörter. Diese Einstellungen gelten für die Passwörter, die Nutzer gegen den IdP selbst setzen — nicht für Service-Accounts oder andere Systeme.
In kleinen Firmen ist eine Praxis, die funktioniert: 12 Zeichen Mindestlänge, keine bekannten Passwörter (Authentik kann Common-Passwort-Listen laden), Protektion gegen Recycling (Passwort darf nicht dem letzten dritten Passwort entsprechen). Für besonders geschützte Accounts (Admin, IdP-Admin) zusätzlich einen Hardware-Schlüssel (YubiKey FIDO2) zu verlangen — Authentik unterstützt WebAuthn (FIDO2) als MFA-Methode, die ist im Enterprise-Kontext einer kleinen Firma eine sinnvolle Investition.
Interne Konten deaktivieren
Wenn ein Mitarbeiter die Firma verlässt, deaktivierst du sein Konto in Authentik (nicht löschen — das würde Audit-Logs verbuchen, die Referenz auf das alte Konto verlieren). Deaktivierung unter Benutzer → Ausgewählter Benutzer → Konto deaktivieren.
Die Auswirkung: Der Benutzer kann sich nicht mehr anmelden. OIDC-Client-Tokens, die bereits ausgestellt wurden und noch nicht abgelaufen sind — die sind durch das Deaktivieren nicht sofort ungültig. In der Praxis setzt du da zwei Dinge: 1) Deaktivierung des Kontos (sofortiger Login-Ausschluss), 2) evtl. manuelle Revokation der Tokens (wenn das Risiko besteht, dass der Ex-Mitarbeiter Zugang zu einem Dienst hat, der noch ein gültiges Token hält).
Authentik hat eine API, über die sich das automatisieren lässt — in Verbindung mit einem HR-System oder manuell per Skript. In kleinen Firmen mit fünf bis 50 Mitarbeitern reicht es oft, das manuell zu tun und es als Teil des offboarding Prozesses zu dokumentieren.
Vergleich mit interner PKI und Caddy — wo die Dsseuden liegen
BsN hat bereits zwei verwandte Artikel veröffentlicht, die konzeptionell verwandt sind, aber andere Schichten abdecken:
| Schicht | BSI/Interne PKI-Artikel | Caddy-Artikel | SSO-Artikel (dieser) |
|---|---|---|---|
| Was | Zertifikate und Verschlüsselung für Dienste im eigenen Netz — Root-CA, Intermediate, Zertifikatsvergabe an Dienste | Reverse Proxy mit automatischen Zertifikaten oder manueller Terminierung; TLS-Konfiguration für mehrere Dienste | Authentifizierungsschicht: wer darf auf einen Dienst zugreifen, zentral entschieden über OIDC/SAML |
| Abhängigkeit | PKI ist unabhängig von SSO — ein Dienst kann ein eigenes Zertifikat haben, ohne SSO. SSO benötigt aber TLS, sonst sind Tokens in der Luft. | Caddy kann TLS für den Authentik-IdP und den Beispiel-Service gleichzeitig übernehmen. Caddy ist nicht zwingend für SSO nötig, aber praktisch, weil TLS ohne Caddy manuell pro Dienst konfiguriert werden muss. | SSO setzt TLS voraus (sonst sind Authorization-Code und Tokens im Klartext im Netz). SSO setzt PKI nicht voraus (Zertifikate kann man von einer privaten CA oder einer öffentlichen CA beziehen). |
| Typische Fehler | Zertifikatsablauf, Zertifikate für den falschen Hostnamen, Root-CA nicht vertraut auf Client-Geräten | Caddy nicht konfiguriert für mehrere Domains, Zertifikat-Provisionierung fehlerhaft bei internen Domains | SSO konfiguriert, aber Dienste erreichbar ohne SSO (kein Schutz, weil Reverse Proxy nicht konfiguriert ist, SSO zu erzwingen) |
Eine typische Architektur für eine kleine Firma sieht so aus: Interne PKI (via BsN-Artikel) vergibt Zertifikate für alle Dienste, Caddy (via BsN-Artikel) terminiert TLS und routet Traffic, und Authentik (dieser Artikel) sitzt vor oder hinter dem Caddy und authentifiziert Nutzer auf Diensten, die OIDC unterstützen. Dienste, die kein OIDC/SAML unterstützen, bleiben ohne SSO schutz — das ist eine Einschränkung, die du akzeptieren musst, oder du setzt eine alternative Schutzschicht.
Häufige Fehler — drei realistische Beispiele
Fehler 1: Redirect URI stimmt nicht exakt überein
Symptom: Nach dem Login auf Authentik kommt eine Fehlermeldung: „Invalid redirect URI" oder der Nutzer wird abgelehnt, ohne dass ein Token ausgestellt wird.
Ursache: Der Redirect URI, den der Client im Authorization-Request sendet, stimmt nicht exakt mit dem Redirect URI überein, den du in der Authentik-OIDC-Client-Konfiguration eingetragen hast. Ein häufiger Fall: https://python-service.brillianze.de/callback in Authentik, aber im Client steht http:// statt https://, oder ein abschließender Schrägstrich ist vorhanden (/callback/ statt /callback).
Lösung: Redirect URIs in OAuth2 sind case-sensitiv und müssen exakt übereinstimmen. Prüfe in Authentik, was konfiguriert ist, und prüfe im Client-Code, was gesendet wird. curl hilft beim Debuggen — wenn du den Authorization-Request per curl -v sendest, siehst du die exakte URL im Location-Header des Redirects.
Fehler 2: Token-Empfang ohne State-Validierung
Symptom: Der Beispiel-Service funktioniert im Test, aber nach einem Tag merkst du, dass du den state-Parameter nicht validierst.
Ursache: Der state-Parameter im OAuth2-Authorization-Code-Flow dient dem CSRF-Schutz. Ohne Validierung kann ein Angreifer (der den Browser des Nutzers kontrolliert) einen eigenen Authorization-Code einbringen und so die Session des Opfers mit dem eigenen Account verknüpfen. Das ist eine bekannte Attacke (CSRF auf OAuth Authorize-Endpunkten).
Lösung: Der state-Parameter muss im session-Objekt gespeichert werden, bevor der Nutzer zum Authorize-Endpunkt geschickt wird, und nach dem Callback gegen den erhaltenen state validiert werden. authlib macht das in der Standard-Konfiguration automatisch — aber nur, wenn du den state-Parameter nicht selbst überschreibst oder die Session nicht deaktivierst. Prüfe in der authlib-Dokumentation für Flask, ob die Default-State-Handhabung aktiv ist. Für den Beispiel-Service ohne State-Validierung ist das ein Sicherheitsloch — in Produktion beheben.
Fehler 3: SQL-Error nach einem Docker-Compose neustart ohne Datenbank-Persistenz
Symptom: Nach einem Reboot des Servers startet Authentik, meldet aber einen Datenbank-Fehler und die Weboberfläche ist nicht erreichbar.
Ursache: Das docker-compose.yml definiert ein Volume für die PostgreSQL-Daten (./data/postgres:/var/lib/postgresql/data), aber wenn der Pfad falsch gesetzt ist, oder die Docker-Volume-Namenskonvention nicht passt (z.B. bei einem Migrieren auf eine andere Distribution), entsteht eine neue, leere Datenbank bei jedem Start. Die Resultat: Authentik initialisiert sich neu, alle Clients und Benutzer sind weg.
Lösung: Prüfe vor einem Produktiv-Einsatz, ob die Daten nach einem docker compose down && docker compose up -d noch da sind:
docker compose down
docker compose up -d
# Danach: Login mit Admin-Benutzer — funktioniert er noch?
Wenn nein, liegt das Volume falsch. Prüfe docker volume ls und docker inspect <volume-name> auf den Mount-Point.
FAQ
Brauche ich eine GPU für Authentik oder Keycloak?
Nein. Weder Authentik noch Keycloak benötigen GPU-Berechnung. Sie sind Webanwendungen (Python bzw. Java), die ihre Arbeit im CPU-Modus machen. Etwas RAM (2–4 GB) und CPU-Kerne (2+) sind ausreichend; eine GPU bringt keinen Vorteil.
Kann ich Authentik ohne Docker betreiben?
Authentik bringt ein Python-Paket (pip install authentik) und läuft theoretisch ohne Docker. In der Praxis empfiehlt das Authentik-Team Docker oder den Omnibus-Paket (für Debian/Ubuntu, kein Docker nötig). Für einen produktiven Betrieb ohne Docker müsstest du PostgreSQL, Redis, das Authentik-Paket und die Authentik-Webrahmen manuell installieren, konfigurieren und als Systemdienste laufen lassen — das ist mehr Wartung auf dich, als der Docker-Weg. Für ein kleines Homelab oder eine kleine Firma ist Docker die dokumentierte und unterstützte Variante.
Ist Keycloak besser als Authentik?
"Better" hängt vom Anwendungsfall ab. Keycloak hat mehr Features (Identity-Brokering zu anderen IdPs, komplexere Rollen-Engine, SAML-Identity-Provider, User-Federation zu LDAP/AD) — aber mehr Komplexität. Authentik ist simpler, OIDC-first, weniger Konfigurationsaufwand für Standard-Use-Cases. Wenn du eine SAML-lastige Umgebung mit vielen Legacy-Applikationen hast, die nah an AD anbinden wollen, ist Keycloak die sinnvollere Wahl. Wenn du primär moderne Webanwendungen mit OIDC hast, ist Authentik der günstigere Einstieg.
Was ist der Unterschied zwischen OIDC und SAML? Ich dachte, SSO heißt SSO.
OIDC (OpenID Connect) ist ein moderner Standard auf dem HTTPS-Protokoll, JSON-basiert, mit JWT-Tokens — er ist das Protokoll der Wahl für neue Webanwendungen. SAML (Security Assertion Markup Language) ist älter, XML-basiert, schwerer zu handhaben, aber noch in vielen Enterprise- und Legacy-Umgebungen verbreitet (insbesondere bei SOAP-basierten Applikationen und bestimmten Single-Sign-On-Lösungen von Herstellern). Beide lösen SSO — aber OIDC ist leichter zu integrieren in moderne Tech-Stacks, SAML ist in bestimmten Legacy-Kontexten das, was man braucht.
Was passiert, wenn Authentik kompromittiert wird?
Wenn ein Angreifer Zugang zum Authentik-Server und zu seinen Secrets (insbesondere dem AUTHENTIK_SECRET_KEY und den OIDC-Client-Secrets) erhält, kann er Tokens für sich selbst ausstellen, die von verbundenen Diensten als gültig angesehen werden. Das ist der schlechteste Fall. Gegenmaßnahmen: Authentik auf einem dedizierten Server oder mindestens isoliert von anderen Diensten betreiben, Zugriff auf den Server streng begrenzen (nur SSH-Key, kein Passwort-Login, Firewall, Security-Updates), Backups verschlüsselt und extern halten, Secrets nicht in unverschlüsselten Konfigurationsdateien ablegen. Für besonders kritische Umgebungen ist eine ausgelagerte IdP- Variante (Cloudflare Access, ein anderer Managed IdP) eine Alternative — aber mit den Datenabhängigkeiten, die das mit sich bringt.
Interne Verlinkungsvorschläge
1. sicherer-fernzugriff.md — „Sicher von unterwegs auf den Heimserver zugreifen: Tailscale, WireGuard und Reverse-Tunnel im Vergleich" — Verlinkung im Abschnitt zur Architektur: Der SSO-IdP ist meist über den eigenen Reverse Proxy von außen erreichbar; wie du den Tunnel schützt und die Zugänglichkeit regelst, steht in diesem Artikel.
2. docker-vs-vm.md — „Docker-Container vs. VM: Wann welcher Virtualisierungstyp das Richtige ist" — Verlinkung in der Docker-Compose-Anleitung: Wenn dein Server ein Hypervisor ist, kannst du Authentik auch als VM statt als Container betreiben; die Entscheidungshilfe in diesem Artikel hilft dir, die Infrastruktur-Entscheidung zu treffen.
3. Artikel zur internen PKI und Caddy (falls verfasst — andernfalls interner Platzhalter) — Verlinkung im TLS-Abschnitt: Wie du Zertifikate für den Authentik-IdP und den Beispiel-Service beschaffst und einsetzt, steht im PKI-Artikel; die Caddy-Konfiguration für Reverse Proxy steht im Caddy-Artikel.
4. Artikel über Passwort-Management und 2FA in der Firma (falls existent — andernfalls Verweis auf BsN-Praxis) — Verlinkung im Passwortrichtlinien-Abschnitt: Wie du YubiKey/FIDO2 in Authentik einbindest, User-Registration für MFA und Betrieb von Hardware-Schlüsseln in kleinen Teams — sobald dieser Artikel existiert.
Bildvorschläge
**Bild 1: SSO-aal"
- Typ: Diagramm (Flussdiagramm, schematisch)
- Inhalt: Nutzer im Browser → IdP-Login-Seite (Authentik) → Redirect mit Code → Beispiel-Python-Service empfängt Token → Zugriff auf geschützte Ressource. Pfeile mit Bezeichnungen: Authorization Request, Authorization Code, Access Token, Userinfo.
- Alt-Text: "Ablaufdiagramm des OAuth2-Authorization-Code-Flows zwischen Browser, Authentik-IdP und einem Beispiel-Python-Service: Der Nutzer ruft den geschützten Service auf, wird zum IdP weitergeleitet, meldet sich dort an und löst den Code gegen einen Access-Token aus, den der Service zur Authentifizierung nutzt."
Bild 2: Vergleichstabelle der drei Kandidaten
- Typ: Tabelle als Grafik (oder direkt als Markdown-Tabelle — das ist in HTML einfacher)
- Inhalt: Die Tabelle aus dem Artikel mit Authentik, Keycloak, Cloudflare Access als Spalten — Protokolle, Benutzerverzeichnis, Lizenzkosten, Hardwarebedarf, Bedienaufwand, Eignung — visuell hervorgehoben als zentrale Entscheidungshilfe.
- Alt-Text: "Vergleichstabelle von Authentik, Keycloak und Cloudflare Access nach Protokoll (OIDC/SAML), Benutzerverzeichnis, Lizenzkosten, Hardwarebedarf, Bedienaufwand und Eignung für kleine Firmen und Homelab-Betreiber."
Bild 3: Docker-Compose-Architektur-Skizze
- Typ: Container-Architekturskizze (schematisch, nicht fotorealistisch)
- Inhalt: Drei Container (PostgreSQL, Redis, Authentik) in einem Docker-Netzwerk, plus ein separater Container für den Beispiel-Python-Service, hinter einem Caddy-Reverse-Proxy. Beschriftungen für die Verbindungen (TLS, OIDC-Protokolle).
- Alt-Text: "Skalarische Docker-Compose-Architektur: PostgreSQL und Redis als Backend-Dienste, Authentik als IdP, ein Beispiel-Python-Service als OIDC-Client, alles über einen Caddy-Reverse-Proxy mit TLS-Terminierung nach außen."
Zielgruppe: Wann ein externer Anbieter wie Cloudflare Access die pragmatischere Wahl ist
Dieser Artikel hat Authentik und Keycloak als selbst-gehostete IdP-Lösungen behandelt. Für viele kleine Firmen (5–50 Mitarbeiter) und fortgeschrittene Homelab-Betreiber ist das der richtige Weg: volle Kontrolle über die Identitätsdaten, keine Abhängigkeit von einem Cloud-Anbieter, keine laufenden Kosten pro Nutzer.
Es gibt Situationen, in denen ein externer Anbieter wie Cloudflare Access die pragmatischere Wahl ist:
- Kein eigener Server für einen IdP vorhanden oder wagemutig: Wenn du keinen 24/7-Rechner für den IdP betreiben willst oder kannst (Kosten, Strom, Wartung, Ausfall-Risiko), ist ein externer IdP mit keinem eigenen Server-Endpunkt eine klare Vereinfachung.
- Domain liegt bereits bei Cloudflare: Wenn du deine Domain und DNS ohnehin bei Cloudflare betreibst und Cloudflare Access ohne zusätzliche Komplexität aktivieren kannst, ist das Einrichten eines Access-Policies über das Dashboard in wenigen Minuten erledigt — im Vergleich zu einer selbst gehosteten IdP, bei der du Server, Datenbank, TLS und Backups selbst verantwortest.
- Web-Dienste mit wenigen Integrationsanforderungen: Wenn deine Dienste primär Web-Applikationen sind, die über den Browser genutzt werden, und Machine-to-Machine-Integrationen (Dienst-zu-Dienst-Auth) nicht zentral sein müssen, reicht Cloudflare Access oft. OIDC für Dienste, die hinter dem Access-Proxy stehen, ist dort konfiguriert; für reine API-Zugänge brauchst du einen anderen Mechanismus.
- Getrennte Identitäten für verschiedene Ziele: Wenn du in Zukunft eine Trennung willst (z.B. Mitarbeiter-Identitäten bei einem Anbieter, Homelab-Identitäten lokal), ist ein externer Anbieter für die Firmenseite eine saubere Trennung — und die Homelab-Seite bleibt bei deinem eigenen IdP, wenn du das willst.
Die Entscheidung ist keine Frage von "right vs. wrong", sondern von den tatsächlichen Bedingungen: Was hast du bereits (Server, Domain, Wartung), was willst du vermeiden (Abhängigkeit, Kosten, Komplexität), und was sind die tatsächlichen Integrationsanforderungen deiner Dienste. Für den typischen BsN-Kunden mit fünf bis 15 Mitarbeitern, einem oder zwei Servern und Web-Diensten, die OIDC unterstützen, ist Authentik mit Docker der beileibe pragmatischste Weg — für Kunden mit mehr Legacy-Anforderungen oder ohne Server-Wunschlust ist Cloudflare Access eine legitime, pragmatische Alternative.
Der Artikel liegt als Markdown-Draft vor (C:\00hermes\unternehmen\artikel-neu\drafts\sso-selbst-gehostet.md) und wurde nicht veröffentlicht. Der Publish-Schritt — HTML-Generierung über das BsN-Build-Skript und Push ins getwo/homelab-vergleich-Repository — ist manuell durch Benjamin durchzuführen, nachdem der Artikel auf inhaltliche Korrektheit geprüft wurde.
Hinweis: Dieser Artikel ist redaktioneller Inhalt und enthält keine Affiliate- oder Partner-Links. Alle Angaben entsprechen dem Stand 2026 und können sich ändern.