spring-projects/spring-security · error · Saml2Exception
Unsupported object of type: " +…
Error message
Unsupported object of type: " + signable.getClass().getName()
What it means
OpenSaml5Template.verify(Object signable) supports signature verification for specific OpenSAML types (e.g. Assertion). If the object passed in is not one of the supported signable types, the template throws Saml2Exception('Unsupported object of type: <className>') because it has no signature verification strategy for that type.
Solutions
- Verify the Assertion object, not the enclosing Response — extract response.getAssertions() and verify each assertion's signature.
- If you need to verify other SAML message types (Response, LogoutRequest), implement signature validation via SignatureTrustEngine directly instead of this template's verify.
- Check call sites so verify() is only invoked with org.opensaml.saml.saml2.core.Assertion instances.
- Log signable.getClass().getName() at the call site to confirm which type is being passed and pick the right verification path.
Example fix
// before
template.verify(response); // Response not supported
// after
for (Assertion assertion : response.getAssertions()) {
template.verify(assertion);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!(signable instanceof Assertion)) {
throw new IllegalArgumentException(
"verify() supports Assertions only; got " + signable.getClass().getName());
} Type guard
boolean isVerifiableAssertion(Object o) {
return o instanceof Assertion a
&& a.getID() != null && a.getIssuer() != null && a.getSignature() != null;
} Try / catch
try {
return template.verify(signable);
} catch (Saml2Exception ex) {
if (ex.getMessage().startsWith("Unsupported object of type")) {
throw new UnsupportedOperationException(
"Verify the Assertion, not " + signable.getClass().getSimpleName());
}
throw ex;
} Prevention
- Pass Assertion objects only; validate the Response envelope separately.
- Check ID/Issuer/Signature are non-null before verifying.
- For Responses/LogoutRequests, use a SignatureTrustEngine-based check instead of template.verify.
- Add a unit test pinning the expected argument type of verify().
When it happens
Trigger: Calling verify(signable) with an XMLObject that is not an Assertion (e.g. a Response, LogoutRequest, AttributeQuery, or arbitrary XMLObject) — the instanceof chain falls through to the final throw.
Common situations: Custom authentication converters verifying the Response envelope's signature instead of the Assertion's; verifying a LogoutRequest/LogoutResponse with the assertion-oriented template API; refactors that changed the argument type passed to verify; generic utility code reusing verify for non-assertion elements.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported object of type:
- Failed to deserialize payload
- Failed to deserialize payload
- Failed to deserialize payload
- Failed to deserialize payload
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/717b7fc5471063b4.
Report an issue: GitHub.
Appendix: source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/authentication/OpenSaml5Template.java:392
if (signable instanceof StatusResponseType response) {
Assert.notNull(response.getID(), "Response#ID cannot be null");
Assert.notNull(response.getIssuer(), "Response#Issuer cannot be null");
Assert.notNull(response.getSignature(), "Response#Signature cannot be null");
return verifySignature(response.getID(), response.getIssuer(), response.getSignature());
}
if (signable instanceof RequestAbstractType request) {
Assert.notNull(request.getID(), "Request#ID cannot be null");
Assert.notNull(request.getIssuer(), "Request#Issuer cannot be null");
Assert.notNull(request.getSignature(), "Request#Signature cannot be null");
return verifySignature(request.getID(), request.getIssuer(), request.getSignature());
}
if (signable instanceof Assertion assertion) {
Assert.notNull(assertion.getID(), "Assertion#ID cannot be null");
Assert.notNull(assertion.getIssuer(), "Assertion#Issuer cannot be null");
Assert.notNull(assertion.getSignature(), "Assertion#Signature cannot be null");
return verifySignature(assertion.getID(), assertion.getIssuer(), assertion.getSignature());
}
throw new Saml2Exception("Unsupported object of type: " + signable.getClass().getName());
}
private Collection<Saml2Error> verifySignature(String id, Issuer issuer, Signature signature) {
SignatureTrustEngine trustEngine = trustEngine(this.credentials);
CriteriaSet criteria = verificationCriteria(issuer);
Collection<Saml2Error> errors = new ArrayList<>();
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
try {
profileValidator.validate(signature);
}
catch (Exception ex) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,
"Invalid signature for object [" + id + "]: "));
}
try {
if (!trustEngine.validate(signature, criteria)) {
errors.add(new Saml2Error(Saml2ErrorCodes.INVALID_SIGNATURE,View on GitHub (pinned to 96852e8860)