spring-projects/spring-security · error · IllegalArgumentException

Failed to decode SAMLResponse

Error message

Failed to decode SAMLResponse

What it means

Base64Checker.checkAcceptable validates that a SAMLResponse parameter is an acceptable Base64 string before decoding: every character must be ignored-or-in-alphabet, the length mod 4 must not be 1, and the unused bits of an incomplete final chunk must be zero. When validation fails it throws IllegalArgumentException('Failed to decode SAMLResponse'). This guards the requireBase64(true) path used when reading the SAMLResponse request parameter.

Source

Thrown at saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/registration/Saml2Utils.java:189

					}
				}

				// in cases of an incomplete final chunk, ensure the unused bits are zero
				switch (goodChars % 4) {
					case 0:
						return true;
					case 2:
						return (lastGoodCharVal & 0b1111) == 0;
					case 3:
						return (lastGoodCharVal & 0b11) == 0;
					default:
						return false;
				}
			}

			void checkAcceptable(String ins) {
				if (!isAcceptable(ins)) {
					throw new IllegalArgumentException("Failed to decode SAMLResponse");
				}
			}

		}

	}

	static class CappedOutputStream extends OutputStream {

		private static final long MAX_SIZE = 1024 * 1024;

		private final OutputStream delegate;

		private int size;

		CappedOutputStream(OutputStream delegate) {
			this.delegate = delegate;
		}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Log the failing samlResponse value (safe, it failed validation) and inspect for HTML entities (&#..;), '+' replaced by ' ', or truncation
  2. URL-decode the parameter before Base64 checking if handling the raw query string yourself; the framework normally does this in request.getParameter
  3. Compare the value length and charset with what the IdP actually sent (capture at the IdP or via network trace)
  4. Treat it as an authentication failure: the Base64 check is a security control; do not bypass it — reject the response
  5. If the IdP legitimately sends non-canonical Base64, verify with getSaml2AuthenticationTokenConverter configuration that requireBase64 applies to your binding

Example fix

// before: raw value contains HTML entities
String encoded = request.getParameter("SAMLResponse"); // "PHNhbWxw...
"
// after: ensure parameter passed through the servlet's URL decoding, or strip whitespace/entity noise
String encoded = request.getParameter("SAMLResponse").replaceAll("\\s", "");
if (encoded == null || encoded.isEmpty()) {
    throw new Saml2AuthenticationException(Saml2Error.invalidResponse("missing SAMLResponse"), null);
}
Defensive patterns

Strategy: validation

Validate before calling

private static final java.util.regex.Pattern B64 = java.util.regex.Pattern.compile("^[A-Za-z0-9+/\\r\\n]+={0,2}$");
boolean acceptableBase64(String s) {
    return s != null && !s.isEmpty() && s.length() % 4 != 1 && B64.matcher(s).matches();
}
if (!acceptableBase64(request.getParameter("SAMLResponse"))) { reject(); }

Type guard

boolean isUsableSamlResponse(String s) { return s != null && s.length() > 8 && s.length() % 4 != 1; }

Try / catch

try { decoding.decode(); } catch (IllegalArgumentException ex) { throw new Saml2AuthenticationException(Saml2Error.invalidResponse("SAMLResponse is not valid Base64"), ex); }

Prevention

When it happens

Trigger: Passing a string that fails the Base64 structural check to Saml2Utils.withEncoded(...).requireBase64(true).decode(): e.g. length % 4 == 1, non-Base64 characters that decode ambiguously, non-zero padding bits in a trailing 2- or 3-character chunk, or a null/empty parameter being validated.

Common situations: IdP or intermediary HTML-escapes or corrupts the SAMLResponse parameter; a load balancer or framework truncates/re-encodes the form value; a client sends tampered or garbage samlResponse values (often malicious probing); custom code feeds a URL-encoded (still %-xx) string in without decoding it first.

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/a58a92b97aec1444. Report an issue: GitHub.