spring-projects/spring-security · error · Saml2Exception

Saml2Exception wrapping DecryptionException during encrypted

Error message

Saml2Exception wrapping DecryptionException during encrypted subject NameID decryption

What it means

decryptSubject decrypts an encrypted NameID on the Assertion's Subject; DecryptionException is wrapped in Saml2Exception. Thrown because the subject's NameID cannot be resolved without successful decryption, which would break downstream identity mapping.

Source

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

				}
				catch (Exception ex) {
					throw new Saml2Exception(ex);
				}
			}
			statement.getAttributes().addAll(decrypteds);
		}

		private void decryptSubject(@Nullable Subject subject) {
			if (subject != null) {
				if (subject.getEncryptedID() != null) {
					try {
						NameID decrypted = (NameID) this.decrypter.decrypt(subject.getEncryptedID());
						if (decrypted != null) {
							subject.setNameID(decrypted);
						}
					}
					catch (final DecryptionException ex) {
						throw new Saml2Exception(ex);
					}
				}

				for (final SubjectConfirmation sc : subject.getSubjectConfirmations()) {
					if (sc.getEncryptedID() != null) {
						try {
							NameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());
							if (decrypted != null) {
								sc.setNameID(decrypted);
							}
						}
						catch (final DecryptionException ex) {
							throw new Saml2Exception(ex);
						}
					}
				}
			}
		}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Add/refresh the SP decryption credential that matches the IDP's NameID encryption certificate.
  2. Check the wrapped DecryptionException cause for 'no key info' vs 'unsupported algorithm'.
  3. Synchronize IDP metadata after key rotation so the SP has the current certificate.
  4. If the IDP supports it, disable NameID encryption or align it with assertion encryption keys.

Example fix

// before
http.saml2Login(relyingPartyRegistrations -> relyingPartyRegistrations.registration(reg)); // reg lacks decryption key
// after
reg = RelyingPartyRegistration.withRelyingPartyRegistration(reg)
    .decryptionX509Credentials(c -> c.add(decryptCredential))
    .build();
Defensive patterns

Strategy: validation

Validate before calling

Assert.notEmpty(registration.getDecryptionX509Credentials(), "configure decryption credential before processing encrypted subjects");

Try / catch

try {
    template.decrypt(response);
} catch (Saml2Exception ex) {
    if (ex.getCause() instanceof DecryptionException) {
        logger.error("Subject NameID decryption failed; check decryption key", ex.getCause());
    }
}

Prevention

When it happens

Trigger: Calling decrypt(...) where subject.getEncryptedID() exists but cannot be decrypted with the configured Decrypter credentials.

Common situations: Missing/mismatched decryption key after IDP cert rotation; IDP encrypts NameID with different key than assertions; algorithm restrictions in OpenSAML 5; SP credential never configured.

Related errors


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