{"record":{"id":"ab59a20587c344b4","repo":"spring-projects/spring-security","slug":"saml2exception-wrapping-decryptionexception-during-ab59a2","errorCode":null,"errorMessage":"Saml2Exception wrapping DecryptionException during encrypted logout-request NameID decryption","messagePattern":"Saml2Exception wrapping DecryptionException during encrypted logout-request NameID decryption","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java","lineNumber":619,"sourceCode":"\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}\n\t\t}\n\n\t}\n\n}\n","sourceCodeStart":601,"sourceCodeEnd":627,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java#L601-L627","documentation":"In the logout-request decryption path (OpenSaml5DecryptionConfigurer / LogoutRequest decryption component), the <EncryptedID> of a LogoutRequest is decrypted to a NameID; a DecryptionException is wrapped in Saml2Exception. Logout processing fails because the IdP-encrypted identifier cannot be recovered.","triggerScenarios":"Processing a SAML Single Logout request containing <EncryptedID> where this.decrypter.decrypt(request.getEncryptedID()) fails: decryption credentials absent/mismatched, or algorithm unsupported by the decrypter configured for logout requests.","commonSituations":"Single Logout enabled with IdP sending encrypted NameIDs but SP only configured decryption for responses (different template/config path); logout decryption credentials not propagated in the OpenSaml5 decryption configurer; IdP rotated its encryption key before a logout request.","solutions":["Ensure the decryption configurer used for logout requests registers the same decryption credentials as the response path","Refresh IdP metadata so the current encryption certificate is available at logout time","Test with a logout request containing a plain (unencrypted) NameID to isolate credential vs config issues","Catch Saml2Exception and inspect the wrapped DecryptionException cause"],"exampleFix":"// before\nOpenSamlDecryptionConfigurer.withDefaults() // logout path, no credentials bound\n// after\nOpenSamlDecryptionConfigurer.withDecryptionCredentials(r -> Set.of(decryptionCredential))","handlingStrategy":"try-catch","validationCode":"if (logoutRequest.getEncryptedID() != null && decryptionCredentials.isEmpty()) throw new Saml2ConfigurationException(\"LogoutRequest EncryptedID but no decryption credentials\");","typeGuard":null,"tryCatchPattern":"try { nameId = decrypter.decrypt(request.getEncryptedID()); } catch (Saml2Exception e) { log.error(\"Logout NameID decryption failed\", e.getCause()); rejectLogout(); }","preventionTips":["Bind decryption credentials in the logout decryption configurer, not only the response path","Test SLO end-to-end with encrypted NameIDs enabled","Refresh IdP metadata before enabling Single Logout"],"tags":["saml","decryption","logout","nameid","spring-security"],"backgroundTag":"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"}