How to support two keys for SAML 2.0 decryption at the same time

Hello!

We have been using Keycloak for two years now successfully, but it is time to replace our expiring certificate/key used for SAML encryption/decryption and we are running into issues.

Our customers each have their own realm set up with a configured SAML 2.0 Identity Provider.
Unless they are using Azure, we have historically recommended that they encrypt their SAML assertions with our public certificate.

To this point, we have just made sure that each realm has our RSA key in place with the public cert/private key combination set to active with a priority of 200 and decryption has never been a problem.

However, we were expecting that we could add our new RSA certificate/key combination in each realm at a higher priority (205) than the existing key and Keycloak would attempt to decrypt with the higher priority one and, if not successful, then attempt to decrypt with the other.
This has not been successful in any test so far.
We are only ever able to log in successfully (without a decryption error) if the (SAML 2.0) Identity Provider’s encryption certificate is the same as the certificate tied to the highest active key in the realm.
If the keys are set to the same priority and both active, it will only be able to decrypt with the key shown first in the UI (Realm Settings → Keys) list.

All documentation we can find seems to be around rotation for signing keys, not keys used for encryption/decryption.
As of now, it appears that there is no way to support two decryption options for a SAML configuration without going realm by realm and updating in coordination with the client updating their (SAML 2.0) IdP’s encryption certificate.

We’ve tried every combination of priority/passive/KeyUse (including adding each key twice and setting one to SIG and one to ENC) that we can think of, but it sounds like this may only be supported for OIDC configurations and not SAML?

Is there something we’re missing? Both keys show up in the (SAML 2.0) IdP metadata link with use="encryption" set, but the second one will never work to successfully decrypt the SAML assertion. This is repeatable 100% of the time.

We have tried this in version 16.1.1 as well as 12.0.4

There’s nothing you have missed.

I run a Keycloak (currently v17) to authorize against a Sibboleth SAML IdP since more than 4 years, started with KC 3. Every year when my KC certificate expires there’s annoying trouble trying to achieve a seamless certificate rollover. A certificate rollover in SAML is done by placing the new certificate next to the old one in the SPs SAML metadata. So the SAML IdP can use both to verify KCs auth request (it automatically finds the correct one) and encrypt the assertion answer sent back to KC, using the certificate which appears on first position in SAML metadata. In that moment where you switch the cert-order on the SAML IdP, Keycloak fails to decrypt. If you don’t change this cert-order and instead switch the usage priority of keys in KC first, KC also fails.

Normally you have time-overlapping priority switches on IdP and on SP with both of them using the one with the highest priority to sign/encrypt, and the other side finding out automatically which one to use to verify/decrypt. But with Keycloak you have to switch the priorities on both partners at exactly the same moment. That’s because Keycloak is not able to find out the correct decryption key. Even if the correct key is configured and active, it stubbornly uses the one with the highest priority to decrypt, and fails.

Keycloak is a very cool and usefull system (I have ~35000 users and ~90 clients configured, customized themes, authenticators/authorizers, having an external LinOTP MFA system connected, …), but: Hundreds of hours are invested to do the change from wildfly → quarkus implementation, for docker and k8s support and that “cloud native” stuff, leaving the really annoing problems in serious production environments unfixed (what about SAML federation support? Even simplesamlphp supports that…)… Sorry for the rant, but these things are really frustrating, maybe I’m too old…:wink: