In an application where spring-security-saml2-service-provider
was upgraded from 6.3.x
to 6.4.1
, I am experiencing a change in behaviour where I'm struggling to access the list of encrypted assertions in a validator class.
I'm configuring a response validator in my configuration as Spring intends by:
var authProvider = new OpenSaml4AuthenticationProvider();
authProvider.setResponseValidator(responseValidator);
Having received a SAML Response with a single encrypted assertion, in said responseValidator
, I'd be able to do something like this:
class SamlResponseValidator implements Converter<ResponseToken, Saml2ResponseValidatorResult> {
@Override
public Saml2ResponseValidatorResult convert(ResponseToken responseToken) {
// Without any other overrides, the below gives you the Spring-decrypted assertion:
var assertions = responseToken.getResponse().getAssertions();
// In 6.3, the below would _also_ contain the still-encrypted assertions while
// in 6.4, you'll always just get an empty list, it seems:
var encryptedAssertions = responseToken.getResponse().getEncryptedAssertions();
// (...)
}
}
I can see that this change comes from what is now OpenSaml4Template.OpenSaml4DecryptionConfigurer.decryptResponse(Response response)
which will do this:
// ...
int count = 0; // <-- This should probably a 1, I assume, otherwise the log statement doesn't make sense
int size = response.getEncryptedAssertions().size();
for (EncryptedAssertion encrypted : response.getEncryptedAssertions()) {
logger.trace(String.format("Decrypting EncryptedAssertion (%d/%d) in Response [%s]", count, size, response.getID()));
try {
Assertion decrypted = this.decrypter.decrypt(encrypted);
if (decrypted != null) {
encrypteds.add(encrypted);
decrypteds.add(decrypted);
}
count++;
} catch (DecryptionException ex) {
throw new Saml2Exception(ex);
}
}
response.getEncryptedAssertions().removeAll(encrypteds); // <-- The cause of what I'm seeing!
response.getAssertions().addAll(decrypteds);
// ...
The Javadoc on the method states that:
The methods that follow are adapted from OpenSAML's [classes].
Previously, response.getEncryptedAssertions().removeAll(encrypteds)
did not exist.
I know that a possible solution is to do responseToken.getToken().getSaml2Response()
and parse it again.
I also now simply override the decrypter that is being used but that would mean a lot of copy and paste of code that I don't actually want to customise (and room for additional bugs and the need for additional tests).
I created a GitHub issue here: https://github.com/spring-projects/spring-security/issues/16367.
Turns out that this was a more or less unintentional change that, as of writing this, will be undone with the next point release.