-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Description
Context: Credential rollover
A SAML 2.0 configuration uses anywhere between 1 to 4 different types of certificates. All of these need to be configured by both the Asserting Party (Identity Provider) and Relying Party (Asserting Party). When one of the certificates expires, this needs to be changed over to a new certificate, preferably without any downtime for the users. This is generally done by configuring two certificates during a rollover window, letting the other party update the certificate and then removing the old one.
The certificate types are:
- Encryption (optional) - Provided by the Identity Provider. Used to encrypt the authentication request. Currently unsupported by Spring Security. Assuming the Identity Provider has configured both credentials configured already, might break the moment the Identity Provider stops supporting the old one.
- Verification (required) - Provided by the Identity Provider. Used to verify the assertions sent by the Identity Provider. Goes correct if both are present in the Metadata XML. Spring Security will pick the one that's been used to sign with.
- Decryption (optional) - Provided by the Service Provider. Used to decrypt encrypted assertions (if used). Goes correct if both are configured in Spring Security. It will pick the one that works.
- Signing (optional) - Provided by the Service Provider. Used to sign the authentication request, if desired by the Identity Provider. This is the main one that currently goes wrong.
Current Behavior
When multiple signing credentials are configured, OpenSAML just picks the first one that satisfies all conditions and signs with it. Since the credentials are stored in a HashSet
(see RelyingPartyRegistration.java
) there is no control over which one it is. If the new signing credentials are used before they are configured on the Identity Provider, this will lead to authentication failures.
Expected Behavior
It should be possible to control which credentials are used for encryption and signing if multiple are known.
One solution is to store the list of credentials in a LinkedHashSet
(I don't really understand why HashSet
s are the default anyway, but I digress). This way the first credential added that satisfies all conditions will be used.
For encryption credentials the newest credentials (with latest expiry) will likely be the best candidate, assuming the Identity Provider has already configured them. If the data is loaded from a metadata XML, this feels like a likely assumption.
For signing credentials the oldest credentials should be used until they either expire, or the Identity Provider has loaded the new credentials, in which case it's safe to remove the old ones.
Context
Spring Security version: 5.5.3, but looking through the git sourcecode, there have been no significant changes here.
OpenSAML version: 3.4.6. OpenSAML 4 also does not seem to have changed as far as I can tell from the source.
- How has this issue affected you? This issue has not affected us yet, but we'd like to have this fixed before the first users can no longer login due to expired certificates.
- What are you trying to accomplish? Implementing a SAML 2.0 credentials rollover mechanism that does not affect users.
- Are you aware of any workarounds? If request signing is disabled, there is no issue. If the Identity Provider can configure multiple verification credentials it's possible to configure the new credentials on the Identity Provider first, and afterwards configure Spring Security. This does mean the metadata XML needs to be bypassed.