spring-projects/spring-security · error · Saml2Exception

Failed to deserialize payload

Error message

Failed to deserialize payload

What it means

The catch-all wrapper in the logout OpenSaml5Template.deserialize(): any non-Saml2Exception exception during parsing or unmarshalling of the SLO payload is rethrown as a Saml2Exception with message "Failed to deserialize payload" and the original exception as cause.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/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. Read ex.getCause() to identify the concrete parser error.
  2. Decode Base64/URL encoding of SAMLRequest/SAMLResponse parameters before calling deserialize().
  3. Validate the XML is well-formed with a standalone parser to locate the defect.
  4. Confirm the payload was not truncated or modified in transit (binding/relay handling).

Example fix

// before
String param = request.getParameter("SAMLRequest");
LogoutRequest lr = template.deserialize(param); // URL/base64 encoded

// after
String xml = new String(Base64.getMimeDecoder().decode(
    URLDecoder.decode(param, StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
LogoutRequest lr = template.deserialize(xml);
Defensive patterns

Strategy: try-catch

Validate before calling

try { new SAXReader().read(new StringReader(serialized)); } catch (Exception e) { throw new IllegalArgumentException("Malformed SLO XML", e); }

Try / catch

try { return template.deserialize(serialized); } catch (Saml2Exception ex) { log.error("SLO payload deserialization failed; cause={}", ex.getCause(), ex); throw ex; }

Prevention

When it happens

Trigger: Calling logout OpenSaml5Template.deserialize(String) where pool.parse() or unmarshaller.unmarshall() throws (malformed XML, bad encoding, IO/SAX errors) other than Saml2Exception.

Common situations: Base64/URL-encoded SLO parameters not decoded before deserialization; truncated logout messages from POST-binding mishandling; invalid XML characters; charset mismatches between IdP and SP.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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