{"record":{"id":"df127335b39c91f8","repo":"spring-projects/spring-security","slug":"saml2exception-wrapping-decryptionexception-during-df1273","errorCode":null,"errorMessage":"Saml2Exception wrapping DecryptionException during encrypted NameID decryption","messagePattern":"Saml2Exception wrapping DecryptionException during encrypted NameID decryption","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java","lineNumber":556,"sourceCode":"\t\t\tfor (AttributeStatement statement : assertion.getAttributeStatements()) {\n\t\t\t\tdecryptAttributes(statement);\n\t\t\t}\n\t\t\tdecryptSubject(assertion.getSubject());\n\t\t\tif (assertion.getConditions() != null) {\n\t\t\t\tfor (Condition c : assertion.getConditions().getConditions()) {\n\t\t\t\t\tif (!(c instanceof DelegationRestrictionType delegation)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tfor (Delegate d : delegation.getDelegates()) {\n\t\t\t\t\t\tif (d.getEncryptedID() != null) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tNameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());\n\t\t\t\t\t\t\t\tif (decrypted != null) {\n\t\t\t\t\t\t\t\t\td.setNameID(decrypted);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch (DecryptionException ex) {\n\t\t\t\t\t\t\t\tthrow new Saml2Exception(ex);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate void decryptAttributes(AttributeStatement statement) {\n\t\t\tCollection<Attribute> decrypteds = new ArrayList<>();\n\t\t\tfor (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {\n\t\t\t\ttry {\n\t\t\t\t\tAttribute decrypted = this.decrypter.decrypt(encrypted);\n\t\t\t\t\tif (decrypted != null) {\n\t\t\t\t\t\tdecrypteds.add(decrypted);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (Exception ex) {\n\t\t\t\t\tthrow new Saml2Exception(ex);","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java#L538-L574","documentation":"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.","triggerScenarios":"Calling decrypt(encryptedAssertion-containing response) where an AttributeStatement's SubjectConfirmationData carries an EncryptedID that cannot be decrypted with the configured Decrypter.","commonSituations":"IDP encrypts NameIDs with a different certificate than assertion encryption; missing decryption credentials; algorithm/key-size restrictions in OpenSAML 5; key rotation mismatch.","solutions":["Ensure the SP's decryption credential matches the certificate the IDP used for the EncryptedID.","Check the wrapped DecryptionException cause to distinguish missing key from unsupported algorithm.","Align encryption method configuration with the IDP or relax OpenSAML 5 algorithm restrictions deliberately.","Re-import the updated IDP metadata after key rotation."],"exampleFix":"// before\n// no decryption credentials configured\n// after\nrelyingPartyRegistration.decryptionX509Credentials(c -> c.add(\n    new Saml2X509Credential(privateKey, cert, Saml2X509CredentialType.DECRYPTION)));","handlingStrategy":"validation","validationCode":"Assert.notEmpty(registration.getDecryptionX509Credentials(), \"decryption credentials required for encrypted NameIDs\");","typeGuard":null,"tryCatchPattern":"try {\n    template.decrypt(response);\n} catch (Saml2Exception ex) {\n    if (ex.getCause() instanceof DecryptionException) {\n        logger.warn(\"Statement-level NameID decryption failed: {}\", ex.getCause().getMessage());\n    }\n}","preventionTips":["Ensure the IDP encrypts all NameIDs with a cert whose private key the SP holds.","Refresh IDP metadata after key rotation.","Log DecryptionException causes to distinguish key-missing vs algorithm issues."],"tags":["saml2","decryption","nameid","opensaml5"],"backgroundTag":"missing-credentials","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}