Repository navigation
Replies: 2 comments 1 reply
|
Your reading is correct: two different layers are involved. The TLS listener decides whether to send a certificate request during the handshake, before an HTTP path or realm is known. The authentication flow decides what to do with a certificate after the handshake. Splitting the realms does not make On one shared listener, the workable setup is If avoiding that prompt is a firm requirement, use separate external TLS endpoints. Portal1's endpoint can require and validate a client certificate; Portal2's endpoint should not request one. They can still forward to one Keycloak deployment, but terminating mTLS at the proxy means the certificate must be forwarded securely. Keycloak's reverse-proxy guide is explicit about the precautions: isolate Keycloak so clients cannot bypass the proxy, overwrite rather than append the certificate header, configure the matching X.509 lookup provider, and enable The authentication mechanism alone does not require two realms. A single realm with a per-client browser-flow override is simpler when the portals should share users, sessions, roles, and administration. Use separate realms when those are security or administrative boundaries; the trade-off is no realm-wide SSO and separate users, roles, clients, and service-account permissions. For the applications, the usual changes are configuration unless values are hard-coded: issuer/discovery URL, JWKS and token validation, redirect and post-logout URIs, Admin REST realm path and credentials, plus realm roles/scopes/audiences. One item that often becomes a code or data issue is user identity: moving a user to another realm gives a different issuer/ |
|
@kally123 here is a concrete nginx setup for the "separate hostname per portal" option. nginx does TLS, and Keycloak runs on plain HTTP behind it, reachable only from nginx. nginx # Portal1 realm: client certificate required
server {
listen 443 ssl;
server_name portal1-auth.example.com;
ssl_certificate /etc/nginx/tls/server.crt;
ssl_certificate_key /etc/nginx/tls/server.key;
ssl_client_certificate /etc/nginx/tls/client-ca.pem; # CA that issued the user certificates
ssl_verify_client on;
ssl_verify_depth 2;
location / {
proxy_pass http://keycloak:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header ssl-client-cert $ssl_client_escaped_cert;
}
}
# Portal2 realm: no client certificate, so no certificate prompt in the browser
server {
listen 443 ssl;
server_name portal2-auth.example.com;
ssl_certificate /etc/nginx/tls/server.crt;
ssl_certificate_key /etc/nginx/tls/server.key;
location / {
proxy_pass http://keycloak:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header ssl-client-cert ""; # drop any header sent by the client
}
}Setting Keycloak 26.1.x bin/kc.sh build --spi-x509cert-lookup-provider=nginx
bin/kc.sh start \
--http-enabled=true \
--proxy-headers=xforwarded \
--hostname=https://portal2-auth.example.com \
--spi-x509cert-lookup-nginx-ssl-client-cert=ssl-client-cert \
--spi-x509cert-lookup-nginx-trust-proxy-verification=true
Then Portal1 apps use |
Uh oh!
There was an error while loading. Please reload this page.
Setup
Two portals, one Keycloak instance:
No password login.
Today both are clients in a single realm. We're evaluating splitting them into
two realms so the authentication mechanisms are fully isolated.
26.1.4Docker container / Manual installation on windowsKeycloak directlyOIDC library, Spring Boot,Nodejs— they talk OIDC for login and use the Admin REST API to create users.The core problem
Everything we've read says authentication flows are realm-scoped, so a realm
split should let each portal authenticate differently. But client-certificate
authentication seems to break that cleanly in two:
X509/Validate Username Formauthenticator is realm-level, buthttps-client-auth— whether the server asks for a client certificate at all— is a server/listener-level setting, and the TLS handshake completes
before Keycloak knows which realm the request is for.
So "realm 1 requires a certificate, realm 2 does not" doesn't appear to be
expressible in realm configuration alone.
Questions
Is that reading correct? Is client-cert negotiation genuinely outside
the realm boundary, or is there a realm-scoped way to require it that we've
missed?
What's the recommended topology for mixing the two? The options we see:
https-client-auth=request(optional) server-wide, with the certificatemade mandatory only inside Portal1's realm authentication flow;
client cert, one not — forwarding the cert via header;
Which is actually used in production, and what are the pitfalls with the
proxy-header route (spoofing protection, cert encoding)?
Does the password portal get a certificate prompt? With
requestrather than
requiredon a shared hostname, do Portal2 users see a browsercertificate-selection dialog they should never see? Is a separate hostname
per portal the only clean way to avoid it?
Two realms, or one realm with per-client authentication flow overrides?
Given the mechanisms differ this much, is a realm split the recommended
isolation, or is a single realm with a flow override per client sufficient
and easier to run? Does the mTLS constraint above change that answer?
What has to change in the applications? We expect config, not code:
issuer / discovery URL (
/realms/{realm}/...), token validation against adifferent issuer, Admin REST API path (
/admin/realms/{realm}/users), aseparate service-account client per realm since
realm-managementroles arerealm-scoped, and possibly a different hostname for Portal1. Is that the
full list? In your experience, what most often forces a real code change
here rather than a config change?
All reactions