spring-projects/spring-security · error · Saml2AuthenticationException

malformed_response_data

malformed_response_data

Error message

malformedResponseData(ex.getMessage())

What it means

parseResponse throws malformed_response_data when the SAML response XML cannot be deserialized by OpenSAML (this.saml.deserialize). This means the received payload is not parseable SAML XML — it is malformed, truncated, HTML (e.g. an error page), or base64-decoded incorrectly.

Source

Thrown at saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/BaseOpenSamlAuthenticationProvider.java:324

		catch (Saml2AuthenticationException ex) {
			throw ex;
		}
		catch (Exception ex) {
			throw new Saml2AuthenticationException(Saml2Error.internalValidationError(ex.getMessage()), ex);
		}
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return Saml2AuthenticationToken.class.isAssignableFrom(authentication);
	}

	private Response parseResponse(String response) throws Saml2Exception, Saml2AuthenticationException {
		try {
			return this.saml.deserialize(response);
		}
		catch (Exception ex) {
			throw new Saml2AuthenticationException(Saml2Error.malformedResponseData(ex.getMessage()), ex);
		}
	}

	private void process(Saml2AuthenticationToken token, Response response) {
		String issuer = issuer(response);
		this.logger.debug(LogMessage.format("Processing SAML response from %s", issuer));
		boolean responseSigned = response.isSigned();

		ResponseToken responseToken = new ResponseToken(response, token);
		Collection<Saml2Error> responseSignatureErrors = this.responseSignatureValidator.convert(responseToken)
			.getErrors();
		if (!responseSignatureErrors.isEmpty()) {
			reportErrors(response, responseSignatureErrors);
			return;
		}

		Collection<Saml2Error> errors = new ArrayList<>();
		if (responseSigned) {

View on GitHub (pinned to 96852e8860)

Solutions

  1. Base64-decode the received SAMLResponse and inspect it — confirm it is well-formed XML with a saml2p:Response root
  2. Verify the ACS URL and binding configuration on both SP and IdP so the IdP posts a real SAML response
  3. Check for proxies/load balancers altering the POST body (compression, chunking, charset issues)
  4. Log the raw response (careful: it may contain PII) to confirm what the IdP actually sends

Example fix

// before
String decoded = new String(Base64.getDecoder().decode(samlResponse)); // may throw on bad input, sent to SP anyway
// after
byte[] bytes = Base64.getMimeDecoder().decode(samlResponse.trim());
if (!new String(bytes, StandardCharsets.UTF_8).contains("<saml2p:Response")) {
    throw new IllegalArgumentException("Not a SAML response");
}
Defensive patterns

Strategy: validation

Validate before calling

byte[] decoded = Base64.getMimeDecoder().decode(samlResponse.trim());
String xml = new String(decoded, StandardCharsets.UTF_8);
if (!xml.contains("<saml2p:Response") && !xml.contains("<Response")) {
    throw new IllegalArgumentException("Payload is not a SAML response XML");
}

Try / catch

try {
    Authentication result = provider.authenticate(token);
} catch (Saml2AuthenticationException e) {
    if (Saml2ErrorCodes.MALFORMED_RESPONSE_DATA.equals(e.getError().getErrorCode())) {
        logger.warn("Unparseable SAMLResponse received; check IdP/ACS configuration", e);
        response.sendError(400);
    }
}

Prevention

When it happens

Trigger: The POSTed SAMLResponse parameter decodes to invalid XML; the IdP returned an HTML error/login page instead of a SAML response; the base64 payload was double-encoded or mangled by the client/proxy; response body truncated.

Common situations: Misconfigured ACS URL causing the IdP to return an error page; proxy servers modifying the POST body; clients sending deflated or non-base64 encodings; single-logout or relay flows where the wrong payload is posted to the assertion consumer endpoint.

Understand the failure class

Related errors


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