Was ist Keycloak?
Keycloak ist eine Open-Source Identity & Access Management (IAM) Lösung, entwickelt von Red Hat und jetzt ein CNCF-Projekt. Es bietet Single Sign-On (SSO), Identity Brokering, User Federation und feingranulare Autorisierung - ohne eigenen Code schreiben zu müssen.
Single Sign-On (SSO)
Einmal anmelden, überall eingeloggt. Unterstützt OpenID Connect, SAML 2.0 und OAuth 2.0.
Identity Brokering
Verbinde externe Identity Provider wie Google, Microsoft, GitHub oder LDAP/Active Directory.
Feingranulare Autorisierung
Realm-Rollen, Client-Rollen, Gruppen und Policy-basierte Zugriffskontrolle.
Multi-Faktor Auth (MFA)
OTP, WebAuthn/Passkeys, SMS und konfigurierbare Authentifizierungs-Flows.
Anpassbare UI
Themes für Login-Seiten, Account-Konsole und Admin-Konsole. Vollständig customizable.
Admin Console
Web-basiertes Management für Users, Clients, Rollen, Sessions, Events und mehr.
Keycloak auf einen Blick
| Eigenschaft | Details |
|---|---|
| Typ | Open Source IAM (CNCF) |
| Aktuelle Version | 26.x (Stand 2026) |
| Protokolle | OpenID Connect, OAuth 2.0, SAML 2.0 |
| Datenbank | PostgreSQL (empfohlen), MySQL, MariaDB |
| Deployment | Docker, Kubernetes, Bare Metal, Cloud |
| Lizenz | Apache License 2.0 |
| Neue Features (v26) | Passkeys, Organizations (CIAM), FAPI 2.0, OAuth 2.0 Server Metadata |
Keycloak Kernkonzepte
Klicke auf die Konzepte, um Details zu sehen:
🌐 Realms
Ein Realm ist der oberste Mandanten-Container. Er verwaltet Users, Credentials, Rollen und Gruppen. Realms sind vollständig voneinander isoliert. Der master-Realm ist für die Administration reserviert - erstelle für jede Anwendungsdomäne einen eigenen Realm.
Beispiel: meine-firma-prod, meine-firma-dev
💻 Clients
Clients sind Anwendungen/Services, die Keycloak zur Authentifizierung nutzen. Jeder Client hat ein Protokoll (OIDC oder SAML) und einen Access-Type:
- Public - Frontend SPA (kein Secret)
- Confidential - Server-seitige App (mit Secret)
- Bearer-only - API, validiert nur Tokens
👥 Users & Groups
Users haben Attribute, Credentials (Passwort, OTP), Gruppenmitgliedschaften und Rollenzuweisungen. Users können lokal erstellt, aus LDAP/AD importiert oder über externe Identity Provider föderiert werden.
Groups sind hierarchische Container. Rollen-Zuweisungen auf Gruppen werden an alle Mitglieder vererbt.
👑 Roles
Zwei Typen von Rollen:
- Realm Roles - Global im Realm (z.B. "admin", "user")
- Client Roles - Scoped auf einen Client (z.B. "api-admin")
Rollen können komposit sein (andere Rollen enthalten). Sie sind der primäre Mechanismus für RBAC.
🔗 Identity Providers
Externe Authentifizierungsquellen. Keycloak kann als Broker fungieren und leitet User an den externen IdP weiter:
- Social - Google, GitHub, Microsoft, Facebook
- Enterprise - SAML IdP, OIDC IdP
- User Federation - LDAP, Active Directory
🔄 Authentication Flows
Konfigurierbare Workflows, die definieren, welche Schritte ein User beim Login durchläuft. Flows bestehen aus geordneten Ausführungen:
- Username/Password Formular
- OTP-Eingabe
- WebAuthn/Passkeys
- Conditional MFA (z.B. nur für bestimmte Clients)
Authentifizierungs-Protokolle
Keycloak unterstützt die wichtigsten Standards für Identity Management:
OpenID Connect (OIDC)
Primäres Protokoll. Basiert auf OAuth 2.0. Liefert ID Token, Access Token und Refresh Token.
Empfohlen für .NET 8
SAML 2.0
Enterprise-Föderations-Protokoll. Keycloak kann als SAML IdP und SAML SP agieren.
Enterprise
OAuth 2.0
Underlying Framework. Token Introspection, Revocation, Device Authorization, PKCE.
Framework
OIDC Authorization Code Flow (mit PKCE)
Der empfohlene Flow für Web-Anwendungen mit .NET 8:
PKCE (Proof Key for Code Exchange) schützt vor Authorization Code Interception Attacks. Immer aktivieren!
Token-Typen
| Token | Zweck | Lebensdauer |
|---|---|---|
| ID Token (JWT) | Enthält User-Identität (Name, Email, Rollen) | Kurz (5-15 Min) |
| Access Token (JWT) | Autorisierung für API-Zugriffe | Kurz (5-15 Min) |
| Refresh Token | Neues Access Token anfordern ohne Re-Login | Lang (Stunden/Tage) |
Plusserver - Deutscher Cloud-Anbieter
Plusserver ist ein führender deutscher Cloud-Provider mit Fokus auf digitale Souveränität und DSGVO-Konformität. Rechenzentren in Köln, Düsseldorf und Hamburg.
pluscloud open
OpenStack-basierte IaaS. Erste deutsche Enterprise Cloud auf Sovereign Cloud Stack (SCS/Gaia-X).
BSI C5 Type II
PSKE - Managed K8s
CNCF-zertifizierte Kubernetes-Plattform auf Basis von SAP Gardener. Autoscaling, Hibernation.
CNCF Certified
Keycloak as a Service
Vollständig gemanagtes Keycloak in deutschen Rechenzentren. Installation, Monitoring, Updates inklusive.
Managed
Zertifizierungen & Compliance
BSI C5 Type II
Bundesamt für Sicherheit in der IT
ISO 27001
Informationssicherheit
DSGVO
EU-Datenschutz-konform
PCI DSS
Payment Card Industry
Keycloak as a Service (KCaaS) - Pricing
Instanz
- 4 vCPU
- 8 GB RAM
- Managed Updates
- 24/7 Support
Storage
- SSD-basiert
- Automatische Backups
- Skalierbar
Inklusive
- SSO & MFA
- Admin Console
- BSI C5 konform
- Kein Mindestvertrag
pluscloud open - Preise
| Ressource | Preis | Hinweis |
|---|---|---|
| vCPU | €0,0205/Stunde | Pay-as-you-go |
| vRAM | €0,007/Stunde pro GB | Pay-as-you-go |
| Storage | €0,09/GB/Monat | SSD |
| Load Balancer | €0,068/Stunde | LBaaS |
| Public IP | €0,003/Stunde | |
| Traffic | Kostenlos | Fair Use |
| Object Storage | 20 GB kostenlos | S3 + Swift kompatibel |
Keycloak Deployment auf Plusserver
Drei Optionen - wähle die passende für dein Team:
Option A: Keycloak as a Service Empfohlen für schnellen Start
Plusserver übernimmt Installation, Monitoring, Updates und Backups.
Vorteil: Kein Infrastruktur-Management, BSI C5 / DSGVO out-of-the-box, 24/7 Support, Pay-as-you-go.
Option B: Self-Managed auf pluscloud open Volle Kontrolle
version: '3.9'
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
keycloak:
image: quay.io/keycloak/keycloak:26.5
command: start
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: ${DB_PASSWORD}
KC_HOSTNAME: auth.meine-firma.de
KC_PROXY_HEADERS: xforwarded
KC_HTTP_ENABLED: "true"
KC_HEALTH_ENABLED: "true"
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: ${ADMIN_PASSWORD}
ports:
- "8080:8080"
depends_on:
- postgres
restart: unless-stopped
volumes:
pgdata:
Nginx Reverse Proxy
server {
listen 443 ssl http2;
server_name auth.meine-firma.de;
ssl_certificate /etc/letsencrypt/live/auth.meine-firma.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/auth.meine-firma.de/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
}
Option C: PSKE Managed Kubernetes Production HA
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
spec:
replicas: 2
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:26.5
args: ["start"]
env:
- name: KC_DB
value: "postgres"
- name: KC_DB_URL
value: "jdbc:postgresql://postgres-svc:5432/keycloak"
- name: KC_DB_USERNAME
valueFrom:
secretKeyRef:
name: keycloak-db
key: username
- name: KC_DB_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak-db
key: password
- name: KC_HOSTNAME
value: "auth.meine-firma.de"
- name: KC_PROXY_HEADERS
value: "xforwarded"
- name: KC_HEALTH_ENABLED
value: "true"
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health/ready
port: 8080
livenessProbe:
httpGet:
path: /health/live
port: 8080
Vergleich der Deployment-Optionen
| Aspekt | KCaaS (Managed) | pluscloud open | PSKE (K8s) |
|---|---|---|---|
| Betriebsaufwand | Minimal | Hoch | Mittel |
| Skalierbarkeit | Begrenzt | Manuell | Auto |
| HA built-in | Ja | Manuell | Mit Replicas |
| Compliance | Vorzertifiziert | Self-managed | Infra vorzertifiziert |
| Anpassbarkeit | Begrenzt | Voll | Voll |
| Best für | Kleine/mittlere Teams | Custom Requirements | Cloud-native Teams |
Keycloak + .NET 8 Backend Integration
Schritt-für-Schritt Anleitung zur Absicherung deines .NET 8 Backends mit Keycloak.
# JWT Bearer Token Validierung (für APIs)
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
# Azure Identity (falls auch Key Vault genutzt wird)
dotnet add package Azure.Identity
# Optional: Keycloak-spezifisches Paket (vereinfacht Config)
dotnet add package Keycloak.AuthServices.Authentication
dotnet add package Keycloak.AuthServices.Authorization
- Keycloak Admin Console öffnen
- Realm auswählen oder erstellen
- Clients → Create client
- Client ID: z.B.
mein-dotnet-api - Client Protocol: openid-connect
- Access Type: confidential
- Valid Redirect URIs:
https://localhost:5001/* - Im Tab Credentials: Client Secret kopieren
Für eine reine API (Bearer-only) kann der Access Type auch auf bearer-only gesetzt werden - dann ist kein Login-Flow nötig.
{
"Keycloak": {
"realm": "mein-realm",
"auth-server-url": "https://auth.meine-firma.de/",
"ssl-required": "external",
"resource": "mein-dotnet-api",
"credentials": {
"secret": "DEIN-CLIENT-SECRET"
}
}
}
Das Client Secret gehört nicht in den Code oder Git! Nutze User Secrets (lokal) oder Azure Key Vault (Produktion).
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
var keycloakUrl = builder.Configuration["Keycloak:auth-server-url"];
var realm = builder.Configuration["Keycloak:realm"];
var audience = builder.Configuration["Keycloak:resource"];
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = $"{keycloakUrl}realms/{realm}";
options.Audience = audience;
options.RequireHttpsMetadata = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidIssuer = $"{keycloakUrl}realms/{realm}"
};
});
builder.Services.AddAuthorization();
builder.Services.AddControllers();
// Claims Transformation für Keycloak-Rollen
builder.Services.AddTransient<IClaimsTransformation,
KeycloakRoleClaimsTransformation>();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
using Keycloak.AuthServices.Authentication;
using Keycloak.AuthServices.Authorization;
var builder = WebApplication.CreateBuilder(args);
// Keycloak Auth in einer Zeile!
builder.Services
.AddKeycloakWebApiAuthentication(builder.Configuration);
// Keycloak-spezifische Autorisierung
builder.Services.AddKeycloakAuthorization(options =>
{
options.EnableRolesMapping =
RolesClaimTransformationSource.ResourceAccess;
options.RolesResource = "mein-dotnet-api";
});
builder.Services.AddAuthorization();
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Achtung: Keycloak verschachtelt Rollen in realm_access.roles und resource_access.<client>.roles im JWT. .NET mappt diese NICHT automatisch auf ClaimTypes.Role!
using System.Security.Claims;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication;
public class KeycloakRoleClaimsTransformation
: IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(
ClaimsPrincipal principal)
{
var identity = (ClaimsIdentity)principal.Identity!;
// Realm Roles
var realmAccess = principal.FindFirst("realm_access");
if (realmAccess != null)
{
var roles = JsonDocument
.Parse(realmAccess.Value)
.RootElement.GetProperty("roles");
foreach (var role in roles.EnumerateArray())
{
identity.AddClaim(new Claim(
ClaimTypes.Role,
role.GetString()!));
}
}
return Task.FromResult(principal);
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
// Nur authentifizierte User
[HttpGet]
[Authorize]
public IActionResult GetAll()
=> Ok("Authentifiziert!");
// Nur User mit Rolle "admin"
[HttpGet("admin")]
[Authorize(Roles = "admin")]
public IActionResult GetAdmin()
=> Ok("Admin-Bereich!");
// Policy-basierte Autorisierung
[HttpDelete("{id}")]
[Authorize(Policy = "RequireManager")]
public IActionResult Delete(int id)
=> Ok($"Gelöscht: {id}");
}
// In Program.cs Policy registrieren:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("RequireManager", policy =>
policy.RequireRole("manager", "admin"));
});
using System.Security.Claims;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
var config = builder.Configuration;
// ==========================================
// Keycloak JWT Bearer Authentication
// ==========================================
var kcUrl = config["Keycloak:auth-server-url"];
var realm = config["Keycloak:realm"];
var audience = config["Keycloak:resource"];
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.Authority = $"{kcUrl}realms/{realm}";
opt.Audience = audience;
opt.RequireHttpsMetadata = true;
opt.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidIssuer = $"{kcUrl}realms/{realm}"
};
});
// Keycloak Rollen-Mapping
builder.Services
.AddTransient<IClaimsTransformation,
KeycloakRoleClaimsTransformation>();
// Autorisierung mit Policies
builder.Services.AddAuthorization(opt =>
{
opt.AddPolicy("AdminOnly",
p => p.RequireRole("admin"));
opt.AddPolicy("ManagerOrAdmin",
p => p.RequireRole("manager", "admin"));
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
Best Practices
✓ Do's
- TLS überall erzwingen - HTTP in Produktion komplett deaktivieren
- Separate Realms pro Umgebung (Dev/Staging/Prod)
- Managed Identity / Passkeys für Admin-Zugriff
- PostgreSQL als Datenbank verwenden
- Min. 2 Replicas für High Availability
- MFA erzwingen für sensible Realms
- Event Logging aktivieren und an SIEM exportieren
- Signing Keys regelmäßig rotieren
- Admin Console auf separatem Hostname betreiben
- KCaaS von Plusserver für DSGVO-Konformität
✗ Don'ts
- H2-Datenbank in Produktion verwenden
- Master-Realm für App-User nutzen
- Client Secrets im Code hartcodieren
- RequireHttpsMetadata = false in Produktion
- Brute-Force-Protection deaktiviert lassen
- Standard-Admin-Passwort beibehalten
- Alle Protocols/Endpoints aktiviert lassen
- Token-Validierung überspringen
- Keycloak ohne Reverse Proxy exponieren
- Updates ignorieren - jedes Release fixt CVEs
Environments-Strategie
| Umgebung | Keycloak | Secret-Quelle | Plusserver |
|---|---|---|---|
| Development | Docker lokal | User Secrets | - |
| Staging | KCaaS oder PSKE | Key Vault / K8s Secrets | pluscloud open |
| Production | KCaaS (HA) oder PSKE (2+ Replicas) | Key Vault / Sealed Secrets | pluscloud open (geo-redundant) |
Gesamtarchitektur: .NET 8 + Keycloak + Plusserver
Wissenstest: Keycloak & Plusserver
Teste dein Wissen!