spring-projects/spring-security · error · Saml2Exception

Failed to deserialize payload

Error message

Failed to deserialize payload

What it means

OpenSaml5Template.deserialize() catches any non-Saml2Exception failure while parsing or unmarshalling the payload (ParserPool errors, SAX parse errors for malformed XML, unmarshaller runtime failures) and rewraps it in this Saml2Exception with the original as the cause. It signals the input could not be converted into an OpenSAML XMLObject.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/logout/OpenSaml5Template.java:160

	@Override
	public <T extends XMLObject> T deserialize(InputStream serialized) {
		try {
			ParserPool pool = XMLObjectProviderRegistrySupport.getParserPool();
			Assert.notNull(pool, "ParserPool must be configured");
			Document document = pool.parse(serialized);
			Element element = document.getDocumentElement();
			UnmarshallerFactory factory = XMLObjectProviderRegistrySupport.getUnmarshallerFactory();
			Unmarshaller unmarshaller = factory.getUnmarshaller(element);
			if (unmarshaller == null) {
				throw new Saml2Exception("Unsupported element of type " + element.getTagName());
			}
			return (T) unmarshaller.unmarshall(element);
		}
		catch (Saml2Exception ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new Saml2Exception("Failed to deserialize payload", ex);
		}
	}

	@Override
	public OpenSaml5SerializationConfigurer serialize(XMLObject object) {
		Marshaller marshaller = XMLObjectProviderRegistrySupport.getMarshallerFactory().getMarshaller(object);
		Assert.notNull(marshaller, "Marshaller for " + object.getElementQName() + " must be configured");
		try {
			return serialize(marshaller.marshall(object));
		}
		catch (MarshallingException ex) {
			throw new Saml2Exception(ex);
		}
	}

	@Override
	public OpenSaml5SerializationConfigurer serialize(Element element) {
		return new OpenSaml5SerializationConfigurer(element);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Verify the input was fully base64-decoded and, for redirect binding, URL-decoded and inflated before deserializing.
  2. Catch this Saml2Exception and inspect ex.getCause() (usually a SAXParseException) for the exact malformed location.
  3. Log the raw payload (at debug) to spot truncation/encoding corruption; re-fetch if transient.
  4. Reject the request as a protocol violation rather than retrying unmodified input.

Example fix

// before
Response r = template.deserialize(request.getParameter("SAMLResponse"));
// Saml2Exception: Failed to deserialize payload (caused by: Content is not allowed in prolog)
// after
byte[] decoded = Saml2Utils.samlDecode(request.getParameter("SAMLResponse"));
String xml = Saml2Utils.samlInflate(decoded); // redirect binding
try {
    Response r = template.deserialize(xml);
} catch (Saml2Exception ex) {
    logger.warn("Malformed SAML payload", ex.getCause());
    throw new AuthenticationServiceException("Invalid SAMLResponse", ex);
}
Defensive patterns

Strategy: try-catch

Validate before calling

String trimmed = xml == null ? "" : xml.trim();
if (!trimmed.startsWith("<")) {
    throw new IllegalArgumentException("Payload is not XML; check base64/inflate decoding steps");
}

Try / catch

try {
    T obj = template.deserialize(xml);
} catch (Saml2Exception ex) {
    Throwable cause = ex.getCause();
    logger.warn("SAML deserialize failed: {}", cause == null ? ex.getMessage() : cause.getMessage());
    throw new AuthenticationServiceException("Malformed SAML payload", ex);
}

Prevention

When it happens

Trigger: Calling OpenSaml5Template.deserialize(String) with malformed XML: bad encoding, unescaped entities, truncated or doubly-encoded bytes, schema-invalid XML, or when the configured ParserPool fails to parse the string.

Common situations: A misbehaving IdP returns truncated or corrupted SAMLResponse; the caller forgot to base64-/URL-decode (or inflate) before deserializing; tampered payloads fail schema validity; wrong charset assumptions (payload is not UTF-8).

Related errors


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