Deployment guide

Keycloak v26.7.4: 6 CVEs — migrate to Authelia or ZITADEL

Deploy on a VPS Cloud →

Tutorial

Keycloak v26.7.4: 6 CVEs — migrate to Authelia or ZITADEL

Security & Monitoring12 min read10 steps

On September 16, 2026, the Keycloak team released version 26.7.4 with an unusual bulletin: six CVEs patched in one release, including two that let any anonymous actor on the internet crash your server without credentials. If you manage SSO for fewer than ten applications on a VPS, this signal is worth pausing on: is Keycloak still the right tool? This guide reviews all six vulnerabilities, compares lightweight alternatives Authelia and ZITADEL, and lays out a concrete migration path with Keycloak running in parallel.

Contents· Keycloak v26.7.4 — why 6 CVEs in one week change the picture1/10
  1. 01Keycloak v26.7.4 — why 6 CVEs in one week change the picture
  2. 02What each CVE could have allowed — plain-language summary
  3. 03Keycloak vs Authelia vs ZITADEL — choosing for your VPS context
  4. 04Authelia — lightweight SSO for fewer than 10 applications
  5. 05Migrating from Keycloak to Authelia — OIDC export, config, tests
  6. 06ZITADEL — API-first identity provider for development teams
  7. 07Migrating from Keycloak to ZITADEL — procedure on VPS
  8. 08Keeping Keycloak running in parallel — the clean cutover strategy
  9. 09Common mistakes during SSO migration
  10. 10After migration — testing authentication for each application

Keycloak v26.7.4 — why 6 CVEs in one week change the picture

The 26.7.4 release notes landed on September 16, 2026, one week after 26.7.3 had already closed several holes. This cadence reveals less an isolated bug than a structural debt in Keycloak's exposure surface: the project supports dozens of protocols (OIDC, SAML, LDAP, Kerberos), a full admin UI, and a server-side theme engine. Each layer carries its own network surface.

The two most severe vulnerabilities (CVE-2026-79651, CVSS 7.5, and CVE-2026-18212, CVSS 7.5) are particularly emblematic: they allow an unauthenticated attacker to exhaust the Keycloak process's memory by hitting publicly accessible endpoints — the login page and SAML endpoints — with no account required. On a VPS with 2–4 GB of RAM shared across several services, such a vector can take down the entire stack.

Another signal: version 26.7.1, released a few weeks earlier, had already introduced security regressions that 26.7.4 only partially fixes (CVE-2026-74909 is explicitly documented as an "incomplete fix" from 26.7.1). Two patch cycles in under a month on consecutive minor versions is a sign that the surface code is under pressure.

What each CVE could have allowed — plain-language summary

  • CVE-2026-79651 (CVSS 7.5 — high): Keycloak accepts arbitrary locale tags on theme endpoints with no bounding or validation. An attacker loops unique locales from the public network; each request allocates memory that is never freed. Result: process crash via memory exhaustion, with zero user credentials required.
  • CVE-2026-18212 (CVSS 7.5 — high): SAML Redirect DEFLATE helpers leak native zlib state. A malformed SAML request is enough to trigger memory corruption that can lead to a server crash or session data leak.
  • CVE-2026-74909 (CVSS 8.1 — high): a percent-encoded semicolon (%3B) bypasses matrix-parameter stripping in PathMatcher. An attacker can reach a resource protected by a stricter policy by using the less-restrictive form of the same route.
  • CVE-2026-90997 (CVSS 7.4 — high): on MySQL or MariaDB deployments, default row counts returned by the storage engine make anti-replay gates ineffective. A previously used authentication artifact can be reused.
  • CVE-2026-17526 (CVSS 7.2 — high): the impersonation role can impersonate a realm administrator. An operator with limited permissions can elevate their privileges to full realm administration.
  • CVE-2026-19607 (CVSS 5.3 — medium): a username collision in the identity federation (broker) flow locks the legitimate user out of their own account without any action on their part.

Keycloak vs Authelia vs ZITADEL — choosing for your VPS context

Scroll the table

CriterionKeycloak 26.7.4Authelia 4.xZITADEL 2.x
RAM at rest512 MB – 1 GB (JVM)< 30 MB (Go)150 – 300 MB (Go + CockroachDB or PostgreSQL)
Language / runtimeJava (JVM)Go — single binaryGo — single binary
LicenseApache 2.0Apache 2.0Apache 2.0 (core)
ProtocolsOIDC, SAML, LDAP, Kerberos, WebAuthnOIDC, 2FA (TOTP, WebAuthn)OIDC, OAuth2, SAML, LDAP, WebAuthn
Admin interfaceFull — realms, clients, flowsYAML onlyWeb console + gRPC/REST API
Best for> 20 apps, LDAP federation, enterprise SAML< 10 apps, proxy auth, technical team< 20 apps, dev team, API-first
VPS maintainabilityHeavy: JVM, XML config, migrationsLight: 1 YAML file, 1 binaryMedium: database required, but clean API
CVE surface (history)High: 6 CVEs in v26.7.4 aloneLow: < 5 CVEs since 2022Low to medium: younger project

Authelia — lightweight SSO for fewer than 10 applications

Authelia is an authentication and authorization server written in Go. It exposes an HTTP validation endpoint that your reverse proxy (nginx, Traefik, Caddy) can query to protect applications without those applications needing to implement OIDC themselves. It also supports the full OIDC flow for applications that require it.

Its memory footprint is its main operational strength: at idle, Authelia consumes between 20 and 30 MB of RAM according to measurements published in the project's GitHub issues (discussions #5939 and #6048). On a 2 GB VPS shared among Nextcloud, a mail server, and a reverse proxy, this is negligible — compared to Keycloak's 512 MB minimum before any load.

Configuration is entirely declarative (YAML). There is no graphical admin interface — an advantage for security (no exposable admin endpoint) and a drawback for non-technical teams. For a solo developer or a small team managing their own VPS applications, Authelia is often the right choice.

Migrating from Keycloak to Authelia — OIDC export, config, tests

  1. Export your OIDC configuration from Keycloak

    In the Keycloak admin console, go to Realm Settings → Export. Check "Export clients" and "Export groups". Download the resulting JSON — it contains your OIDC clients with their redirect URIs and scopes. This file serves as a reference for reconfiguring each application in Authelia; it is not imported directly.

  2. Install Authelia with Docker Compose

    Create a minimal docker-compose.yml:

    services:
    authelia:
    image: authelia/authelia:latest
    volumes:
    - ./config:/config
    ports:
    - 9091:9091
    restart: unless-stopped

    Create the config/ directory and place configuration.yml inside it. The official documentation provides a complete skeleton at https://www.authelia.com/configuration/prologue/introduction/.

  3. Configure OIDC clients in Authelia

    For each application migrated from Keycloak, add an entry under identity_providers.oidc.clients in configuration.yml:

    identity_providers:
    oidc:
    clients:
    - id: my-app
    secret: '$pbkdf2-sha512$...'
    redirect_uris:
    - https://my-app.example.com/oauth/callback
    scopes: [openid, email, profile]

    Generate the secret with authelia crypto hash generate pbkdf2 --variant sha512. Use the Keycloak export JSON to find each client's redirect URIs.

  4. Configure your reverse proxy to query Authelia

    Authelia works as a validation middleware. In nginx, add an auth_request block:

    location /authelia {
    internal;
    proxy_pass http://authelia:9091/api/authz/forward-auth;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location / {
    auth_request /authelia;
    proxy_pass http://my-app:3000;
    }

    For applications that use OIDC natively, point the issuer to https://auth.your-domain.com.

  5. Test each application before cutting over from Keycloak

    For each migrated application, verify three flows: initial login (redirect to Authelia → authentication → return to app), logout (Authelia cookie and app session invalidated), and second factor if enabled (TOTP or WebAuthn). Only cut over from Keycloak once all flows for all applications are validated on Authelia. Keep the Keycloak container stopped but not deleted for 30 days to allow rollback.

ZITADEL — API-first identity provider for development teams

ZITADEL is an Identity Provider written in Go, licensed under Apache 2.0, published by the Swiss team ZITADEL Cloud. Its official repository is github.com/zitadel/zitadel. Where Authelia is designed as a proxy middleware, ZITADEL is a full-featured IdP with a first-class gRPC/REST API — built for organizations that build applications, not just protect them.

The memory footprint is higher than Authelia because ZITADEL requires a database (PostgreSQL or CockroachDB), but stays in the 150–300 MB range under normal load — well below Keycloak's 512 MB JVM minimum. The project supports OIDC, OAuth2, SAML 2.0, read-only LDAP, and WebAuthn.

ZITADEL is particularly suited to development teams building SaaS applications who need to manage organizations and users programmatically via API, without going through a GUI for every operation. The web console is available but the API is the primary path.

Migrating from Keycloak to ZITADEL — procedure on VPS

  1. Deploy ZITADEL with Docker Compose

    ZITADEL provides an official docker-compose.yml in its GitHub repository (the e2e/ directory). The minimal configuration requires PostgreSQL (or CockroachDB) and a 32-character ZITADEL_MASTERKEY:

    ZITADEL_MASTERKEY=$(openssl rand -base64 32)

    Consult the official documentation at https://zitadel.com/docs/self-hosting/deploy/compose for the complete file and required environment variables.

  2. Create OIDC applications in ZITADEL

    In the ZITADEL console (https://your-instance:8080), create an Organization, then a Project. Inside that project, create an Application of type "Web" or "User Agent" depending on your use case.

    ZITADEL generates a Client ID and Client Secret. Configure the Redirect URIs using your Keycloak export JSON as reference. The Discovery endpoint is at https://your-instance:8080/.well-known/openid-configuration.

  3. Migrate users from Keycloak

    Keycloak can export users from a realm as JSON via the console (Realm Settings → Export → check "Export users"). Hashed passwords cannot be imported directly into ZITADEL — the hashing algorithms differ.

    Two approaches: (1) import user metadata via the ZITADEL API (POST /management/v1/users/human/_import) with forced password reset on first login, or (2) progressive migration via social/OIDC login (ZITADEL consumes Keycloak as an external IdP during the transition). Approach (2) avoids asking all users to reset their passwords on the same day.

  4. Update your applications to point to ZITADEL

    Update environment variables for each application:

    OIDC_ISSUER=https://your-instance:8080
    OIDC_CLIENT_ID=<zitadel-client-id>
    OIDC_CLIENT_SECRET=<zitadel-client-secret>

    The Discovery endpoint allows most OIDC libraries to self-configure. Test each application with a test account before switching production traffic.

  5. Validate SSO flows and disable Keycloak

    Verify login, logout, token refresh, and second factor on each application. In ZITADEL, the "Sessions" tab in the console lets you see active sessions in real time and invalidate them if needed.

    Keep the Keycloak container stopped but not deleted for 30 days. Delete it after this retention period.

Keeping Keycloak running in parallel — the clean cutover strategy

The classic objection to migrating an IdP is valid: all your applications share the same identity provider. If the migration fails halfway through, no one can log in.

The recommended strategy is to keep Keycloak operational throughout the migration and cut over applications one at a time. Several mechanisms make this straightforward:

Per-application DNS: each application points to an IdP via an environment variable. Change OIDC_ISSUER for one application at a time, test, then move to the next. Keycloak continues serving applications not yet migrated.

Independent sessions: OIDC creates independent application sessions. An application migrated to Authelia or ZITADEL does not invalidate active sessions for applications still on Keycloak.

30-day window: most migrations of fewer than 10 applications take 2 to 5 days of technical work. Plan for a week, validate for 30 days, then cut over. The docker compose stop keycloak command is reversible in 30 seconds.

Common mistakes during SSO migration

Four pitfalls recur consistently in Keycloak-to-lightweight migrations.

Forgotten redirect URIs: Keycloak validates redirect URIs exactly by default. Authelia and ZITADEL do the same. If your application sends https://app.example.com/callback but the IdP configuration declares https://app.example.com/oauth/callback, authentication fails with a redirect_uri_mismatch error. Check each URI in the Keycloak export JSON.

Scopes and claims are not identical: Keycloak can be configured to return custom claims (roles, user attributes) that your applications consume. Authelia returns only openid, profile, and email by default. If your application depends on a roles or groups claim, verify that your target IdP can produce it before cutting over from Keycloak.

IdP session and application session are distinct: a logout from the IdP does not automatically log out the application if it does not implement back-channel logout. Users may remain logged in to an application after being logged out of the IdP. Test the full logout flow explicitly.

Clock skew invalidates tokens: OIDC tokens have a short validity window (typically 5 to 15 minutes). If your VPS clock drifts by more than a few dozen seconds, tokens expire before they are used. Verify that chrony or systemd-timesyncd is active on your VPS with timedatectl status.

After migration — testing authentication for each application

An SSO migration is not complete when the first login works. Here is the minimum validation checklist to apply to each application.

Initial login: open a private browsing session (no existing cookies) and log in. The redirect to the IdP must work, authentication must succeed, and the return to the application must land on the correct page.

Refresh token: wait for the access token to expire (or force it in a dev environment) and verify that the application silently refreshes the token without forcing a re-login.

Logout: log out from the application and verify that the session is invalidated on the IdP side (Authelia: authelia_session cookie absent; ZITADEL: session absent from the console). Attempt to access a protected resource after logout — you should be redirected to the login page.

Second factor: if 2FA is enabled, test TOTP and WebAuthn separately. WebAuthn sessions are domain-bound — a simultaneous domain migration would invalidate all existing passkeys.

Unauthorized access: attempt to access a protected resource without a valid token and verify that the response is a 401 or a redirect to the IdP, not a 500 or an application page without data.

Authelia or ZITADEL deployed on your VPS in minutes

ServOrbit offers Authelia as a marketplace application. Deploy lightweight SSO on your VPS without manual Docker Compose configuration.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab