{"record":{"id":"f4b3f6ee78700d02","repo":"spring-projects/spring-security","slug":"saml2exception-wrapping-decryptionexception-during-f4b3f6","errorCode":null,"errorMessage":"Saml2Exception wrapping DecryptionException during encrypted subject-confirmation NameID decryption","messagePattern":"Saml2Exception wrapping DecryptionException during encrypted subject-confirmation NameID decryption","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java","lineNumber":603,"sourceCode":"\t\t\t\t\t\tif (decrypted != null) {\n\t\t\t\t\t\t\tsubject.setNameID(decrypted);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch (final DecryptionException ex) {\n\t\t\t\t\t\tthrow new Saml2Exception(ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (final SubjectConfirmation sc : subject.getSubjectConfirmations()) {\n\t\t\t\t\tif (sc.getEncryptedID() != null) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tNameID decrypted = (NameID) this.decrypter.decrypt(sc.getEncryptedID());\n\t\t\t\t\t\t\tif (decrypted != null) {\n\t\t\t\t\t\t\t\tsc.setNameID(decrypted);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (final DecryptionException ex) {\n\t\t\t\t\t\t\tthrow new Saml2Exception(ex);\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 decryptLogoutRequest(LogoutRequest request) {\n\t\t\tif (request.getEncryptedID() != null) {\n\t\t\t\ttry {\n\t\t\t\t\tNameID decrypted = (NameID) this.decrypter.decrypt(request.getEncryptedID());\n\t\t\t\t\tif (decrypted != null) {\n\t\t\t\t\t\trequest.setNameID(decrypted);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (DecryptionException ex) {\n\t\t\t\t\tthrow new Saml2Exception(ex);\n\t\t\t\t}\n\t\t\t}","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java#L585-L621","documentation":"OpenSaml5Template.decryptSubject also iterates SubjectConfirmations and decrypts each <saml2:EncryptedID> inside them. A DecryptionException there is wrapped in a Saml2Exception. This means an encrypted NameID embedded in a SubjectConfirmation (common in Holder-of-Key / bearer confirmation) failed to decrypt.","triggerScenarios":"decryptAssertion -> decryptSubject when SubjectConfirmation(s) contain EncryptedID elements; decryption credentials don't match or the ciphertext/algorithm is unsupported.","commonSituations":"IdP encrypts the SubjectConfirmation NameID with a different certificate than the subject NameID; SP only registered one decryption key; proxy/pass-through SSO flows where an intermediary's key was expected.","solutions":["Register all decryption credentials the IdP may use, including those for SubjectConfirmation EncryptedIDs","Check the caught DecryptionException and its KeyInfo against each registered certificate","Confirm key agreement/key-transport algorithms (RSA-OAEP, ECDH-ES) are supported by the JVM","Sync encryption certificates in both SP and IdP metadata"],"exampleFix":"// before\nc -> c.add(credA) // only one decryption credential\n// after\nc -> c.add(credA).add(credB) // all certs the IdP may encrypt to","handlingStrategy":"try-catch","validationCode":"for (SubjectConfirmation sc : subject.getSubjectConfirmations()) {\n    if (sc.getEncryptedID() != null && registration.getDecryptionX509Credentials().isEmpty())\n        throw new IllegalStateException(\"Encrypted SubjectConfirmation NameID without credentials\");\n}","typeGuard":"if (sc.getEncryptedID() == null && sc.getNameID() != null) { /* already plain */ }","tryCatchPattern":"try {\n    decryptSubject(subject);\n} catch (Saml2Exception ex) {\n    if (ex.getCause() instanceof DecryptionException)\n        logger.warn(\"SubjectConfirmation NameID decryption failed\");\n    throw ex;\n}","preventionTips":["Register every certificate the IdP might encrypt to, not just one","Check KeyInfo inside each SubjectConfirmation EncryptedID against registered certs","Coordinate SSO and SLO certificate configs on the IdP side"],"tags":["saml2","decryption","subject-confirmation","nameid","spring-security"],"backgroundTag":"saml-decryption-failed","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"}