{"record":{"id":"58846b2110bd1f71","repo":"spring-projects/spring-security","slug":"saml2exception-wrapping-securityexception-while-si-58846b","errorCode":null,"errorMessage":"Saml2Exception wrapping SecurityException while signing query string (redirect binding)","messagePattern":"Saml2Exception wrapping SecurityException while signing query string \\(redirect binding\\)","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":279,"sourceCode":"\t\t\tCredential credential = parameters.getSigningCredential();\n\t\t\tAssert.notNull(credential, \"credential cannot be null when signing a SAML payload\");\n\t\t\tString algorithmUri = parameters.getSignatureAlgorithm();\n\t\t\tAssert.notNull(algorithmUri, \"algorithmUri cannot be null when signing a SAML payload\");\n\t\t\tthis.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);\n\t\t\tUriComponentsBuilder builder = UriComponentsBuilder.newInstance();\n\t\t\tfor (Map.Entry<String, String> component : this.components.entrySet()) {\n\t\t\t\tbuilder.queryParam(component.getKey(),\n\t\t\t\t\t\tUriUtils.encode(component.getValue(), StandardCharsets.ISO_8859_1));\n\t\t\t}\n\t\t\tString queryString = builder.build(true).toString().substring(1);\n\t\t\ttry {\n\t\t\t\tbyte[] rawSignature = XMLSigningUtil.signWithURI(credential, algorithmUri,\n\t\t\t\t\t\tqueryString.getBytes(StandardCharsets.UTF_8));\n\t\t\t\tString b64Signature = Saml2Utils.samlEncode(rawSignature);\n\t\t\t\tthis.components.put(Saml2ParameterNames.SIGNATURE, b64Signature);\n\t\t\t}\n\t\t\tcatch (SecurityException ex) {\n\t\t\t\tthrow new Saml2Exception(ex);\n\t\t\t}\n\t\t\treturn this.components;\n\t\t}\n\n\t\tprivate SignatureSigningParameters resolveSigningParameters() {\n\t\t\tList<Credential> credentials = resolveSigningCredentials();\n\t\t\tList<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);\n\t\t\tString canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;\n\t\t\tSignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();\n\t\t\tBasicSignatureSigningConfiguration signingConfiguration = new BasicSignatureSigningConfiguration();\n\t\t\tsigningConfiguration.setSigningCredentials(credentials);\n\t\t\tsigningConfiguration.setSignatureAlgorithms(this.algs);\n\t\t\tsigningConfiguration.setSignatureReferenceDigestMethods(digests);\n\t\t\tsigningConfiguration.setSignatureCanonicalizationAlgorithm(canonicalization);\n\t\t\tsigningConfiguration.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());\n\t\t\tCriteriaSet criteria = new CriteriaSet(new SignatureSigningConfigurationCriterion(signingConfiguration));\n\t\t\ttry {\n\t\t\t\tSignatureSigningParameters parameters = resolver.resolveSingle(criteria);","sourceCodeStart":261,"sourceCodeEnd":297,"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#L261-L297","documentation":"OpenSaml5Template wraps OpenSAML's SecurityException in a Saml2Exception when signing a SAML protocol message's query string for the Redirect binding. SecurityException from XMLSigningUtil.signWithURI means the signing credential could not be used to produce the signature (e.g. the credential's private key is unusable or mismatched with the signing algorithm). This uniform Saml2Exception is Spring Security's translation layer so callers only handle one exception type.","triggerScenarios":"Calling OpenSamlSigningUtils/Template.sign() on a query string (redirect binding SignableSAMLObject or query-string path) where resolveSigningParameters produced a credential+algorithm pair that XMLSigningUtil cannot use, e.g. a credential whose private key is not an RSA/EC key compatible with the resolved signature algorithm URI.","commonSituations":"Registering an X509 certificate without the matching private key or a key in a format the JDK provider cannot load; configuring a signatureAlgorithm that does not match the key type (e.g. SHA256withRSA on an EC key); credentials loaded from a broken/wrong keystore so the private key handle is invalid.","solutions":["Verify the signing credential includes a usable RSAPrivateKey/ECPrivateKey matching the certificate","Ensure the configured signatureAlgorithm URI matches the credential key type","Check that the keystore/password configuration loads the private key correctly and log credential.getPrivateKey() != null","Catch Saml2Exception and surface the wrapped SecurityException cause for diagnosis"],"exampleFix":"// before\n.signWith(algorithmRegistry, credentialWithoutPrivateKey)\n// after\n.signWith(SignatureAlgorithm.RSA_SHA256, credential) // credential built from keyStore with matching private key","handlingStrategy":"try-catch","validationCode":"if (credential.getPrivateKey() == null) throw new IllegalStateException(\"Signing credential has no private key\");\nif (!algorithmUri.contains(\"rsa\") && keyIsRsa) throw new IllegalStateException(\"Algorithm/key mismatch\");","typeGuard":"function hasUsableSigningKey(cred) { return cred != null && cred.getPrivateKey() != null; }","tryCatchPattern":"try { signed = signingUtils.sign(...); } catch (Saml2Exception e) { log.error(\"SAML signing failed\", e.getCause()); throw new SamlAuthException(e); }","preventionTips":["Always build signing credentials from a keystore entry containing both certificate and private key","Match signatureAlgorithm to key type (RSA vs EC)","Test redirect-binding signing at startup with a smoke test","Log the wrapped cause, not just Saml2Exception"],"tags":["saml","signature","keystore","spring-security"],"backgroundTag":"saml-signature-credential-unusable","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}