spring-projects/spring-security · error · Saml2Exception

Saml2Exception wrapping DecryptionException during encrypted

Error message

Saml2Exception wrapping DecryptionException during encrypted NameID decryption

What it means

While walking an Assertion's AttributeStatements, an encrypted NameID in each SubjectConfirmationData is decrypted; DecryptionException is wrapped in Saml2Exception. Thrown because a failure to decrypt a statement-level NameID leaves the subject identity unusable.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java:556

			for (AttributeStatement statement : assertion.getAttributeStatements()) {
				decryptAttributes(statement);
			}
			decryptSubject(assertion.getSubject());
			if (assertion.getConditions() != null) {
				for (Condition c : assertion.getConditions().getConditions()) {
					if (!(c instanceof DelegationRestrictionType delegation)) {
						continue;
					}
					for (Delegate d : delegation.getDelegates()) {
						if (d.getEncryptedID() != null) {
							try {
								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
								if (decrypted != null) {
									d.setNameID(decrypted);
								}
							}
							catch (DecryptionException ex) {
								throw new Saml2Exception(ex);
							}
						}
					}
				}
			}
		}

		private void decryptAttributes(AttributeStatement statement) {
			Collection<Attribute> decrypteds = new ArrayList<>();
			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
				try {
					Attribute decrypted = this.decrypter.decrypt(encrypted);
					if (decrypted != null) {
						decrypteds.add(decrypted);
					}
				}
				catch (Exception ex) {
					throw new Saml2Exception(ex);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Ensure the SP's decryption credential matches the certificate the IDP used for the EncryptedID.
  2. Check the wrapped DecryptionException cause to distinguish missing key from unsupported algorithm.
  3. Align encryption method configuration with the IDP or relax OpenSAML 5 algorithm restrictions deliberately.
  4. Re-import the updated IDP metadata after key rotation.

Example fix

// before
// no decryption credentials configured
// after
relyingPartyRegistration.decryptionX509Credentials(c -> c.add(
    new Saml2X509Credential(privateKey, cert, Saml2X509CredentialType.DECRYPTION)));
Defensive patterns

Strategy: validation

Validate before calling

Assert.notEmpty(registration.getDecryptionX509Credentials(), "decryption credentials required for encrypted NameIDs");

Try / catch

try {
    template.decrypt(response);
} catch (Saml2Exception ex) {
    if (ex.getCause() instanceof DecryptionException) {
        logger.warn("Statement-level NameID decryption failed: {}", ex.getCause().getMessage());
    }
}

Prevention

When it happens

Trigger: Calling decrypt(encryptedAssertion-containing response) where an AttributeStatement's SubjectConfirmationData carries an EncryptedID that cannot be decrypted with the configured Decrypter.

Common situations: IDP encrypts NameIDs with a different certificate than assertion encryption; missing decryption credentials; algorithm/key-size restrictions in OpenSAML 5; key rotation mismatch.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/df127335b39c91f8. Report an issue: GitHub.