spring-projects/spring-security · error · Saml2Exception

Saml2Exception wrapping DecryptionException during encrypted

Error message

Saml2Exception wrapping DecryptionException during encrypted NameID decryption

What it means

When decrypting an AttributeStatement, OpenSaml5Template decrypts each Statement's <EncryptedID> into a NameID; a DecryptionException is rethrown as Saml2Exception. It means the encrypted identifier could not be decrypted with the configured decryption credentials.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/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 decryption credential matching the IdP's encryption certificate is registered and its private key is present
  2. Check for IdP key rotation and update the SP's keystore
  3. Agree with the IdP on supported encryption algorithms (e.g. aes128-cbc vs aes256-gcm, rsa-1_5 vs rsa-oaep)
  4. Catch Saml2Exception and inspect cause DecryptionException for key resolution failure details

Example fix

// before
.decryptionX509Certificate(oldIdpEncryptionCert) // stale after IdP key rotation
// after
.decryptionX509Certificate(currentIdpEncryptionCert)
.build()
Defensive patterns

Strategy: try-catch

Validate before calling

if (statement.getEncryptedIDs().stream().anyMatch(e -> e != null) && !hasMatchingDecryptionKey(statement)) throw new Saml2ConfigurationException("No key for encrypted attribute NameID");

Try / catch

try { decrypted = decrypter.decrypt(encryptedId); } catch (Saml2Exception e) { log.warn("Encrypted attribute NameID failed: " + e.getCause()); }

Prevention

When it happens

Trigger: decryptAssertion() traversing AttributeStatements that contain <EncryptedID>, calling this.decrypter.decrypt(d.getEncryptedID()) when the decryption key does not match the encryption key or the algorithm is unsupported.

Common situations: IdP encrypts attribute NameIDs with a key rotation the SP hasn't picked up; SP configured only the signing certificate, not the encryption/decryption certificate; JVM lacks support for the IdP's key-wrap algorithm.

Related errors


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