Skip to content

Saml2LogoutRequest is not completely serializable, leading to errors when using JDBC session store #12765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jankoh opened this issue Feb 22, 2023 · 6 comments
Assignees
Labels
in: saml2 An issue in SAML2 modules status: duplicate A duplicate of another issue type: bug A general bug

Comments

@jankoh
Copy link

jankoh commented Feb 22, 2023

Implementing a SAML2 logout using Spring security's SAML2 implementaion leads to the following exception stacktrace when using Spring's jdbc session store and performing a logout:

org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.Object] to type [byte[]] for value 'org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest@343d1879'
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository.serialize(JdbcIndexedSessionRepository.java:680) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository.lambda$insertSessionAttributes$5(JdbcIndexedSessionRepository.java:565) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.jdbc.core.JdbcTemplate.lambda$update$2(JdbcTemplate.java:963) ~[spring-jdbc-6.0.4.jar:6.0.4]
	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651) ~[spring-jdbc-6.0.4.jar:6.0.4]
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:960) ~[spring-jdbc-6.0.4.jar:6.0.4]
	at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:1015) ~[spring-jdbc-6.0.4.jar:6.0.4]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository.insertSessionAttributes(JdbcIndexedSessionRepository.java:561) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository$JdbcSession.lambda$save$6(JdbcIndexedSessionRepository.java:889) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.transaction.support.TransactionOperations.lambda$executeWithoutResult$0(TransactionOperations.java:68) ~[spring-tx-6.0.4.jar:6.0.4]
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-6.0.4.jar:6.0.4]
	at org.springframework.transaction.support.TransactionOperations.executeWithoutResult(TransactionOperations.java:67) ~[spring-tx-6.0.4.jar:6.0.4]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository$JdbcSession.save(JdbcIndexedSessionRepository.java:874) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository.save(JdbcIndexedSessionRepository.java:473) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.session.jdbc.JdbcIndexedSessionRepository.save(JdbcIndexedSessionRepository.java:139) ~[spring-session-jdbc-3.0.0.jar:3.0.0]
	at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:228) ~[spring-session-core-3.0.0.jar:3.0.0]
	at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:146) ~[spring-session-core-3.0.0.jar:3.0.0]
	at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82) ~[spring-session-core-3.0.0.jar:3.0.0]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) ~[spring-web-6.0.4.jar:6.0.4]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:691) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:443) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:367) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:295) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:372) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:228) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:313) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:153) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.5.jar:10.1.5]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer
	at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:64) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:33) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:386) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-6.0.4.jar:6.0.4]
	... 43 common frames omitted
Caused by: java.io.NotSerializableException: org.springframework.security.saml2.provider.service.authentication.logout.Saml2LogoutRequest$$Lambda$2269/0x0000000801ac9af0
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1187) ~[na:na]
	at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1572) ~[na:na]
	at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1529) ~[na:na]
	at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1438) ~[na:na]
	at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1181) ~[na:na]
	at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:350) ~[na:na]
	at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:46) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.core.serializer.Serializer.serializeToByteArray(Serializer.java:56) ~[spring-core-6.0.4.jar:6.0.4]
	at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:60) ~[spring-core-6.0.4.jar:6.0.4]
	... 46 common frames omitted

Debugging leads to a missing serialization in the default encoder function which is implemented as:

private static final Function<Map<String, String>, String> DEFAULT_ENCODER = (params) -> {
	if (params.isEmpty()) {
		return null;
	}
	UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
	for (Map.Entry<String, String> component : params.entrySet()) {
		builder.queryParam(component.getKey(), UriUtils.encode(component.getValue(), StandardCharsets.ISO_8859_1));
	}
	return builder.build(true).toString().substring(1);
};

Screenshot_20230222_171917
Screenshot_20230222_172010

Removing JDBC session storage resolves the logout problem (but obviously introduces other problems).

To Reproduce

  1. Set up SAML2 logout with activated JDBC session storage
  2. Log in to your application
  3. Log out of your application -> exception

Expected behavior
Log out should succeed.

This is probably similar to #10550, which deals with authentication requests.

@jankoh jankoh added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Feb 22, 2023
@jzheaux
Copy link
Contributor

jzheaux commented Feb 22, 2023

Thanks for the report, @jankoh. I believe this is a duplicate of #12472. We can re-open if you feel I'm in error.

@jzheaux jzheaux closed this as completed Feb 22, 2023
@jzheaux jzheaux self-assigned this Feb 22, 2023
@jzheaux jzheaux added status: duplicate A duplicate of another issue in: saml2 An issue in SAML2 modules and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 22, 2023
@jankoh
Copy link
Author

jankoh commented Feb 23, 2023

Hey @jzheaux, the fix looks like it's resolving the issue. Unfortunately Spring Boot 3 uses Spring Security 6, and the fix is not in Spring Security 6.0.2. That has probably been missed.

@jankoh
Copy link
Author

jankoh commented Mar 2, 2023

@jzheaux any news on the 6.X versions? Spring Boot 3.0.3 still ships the bug via its dependencies.

@jankoh
Copy link
Author

jankoh commented Mar 23, 2023

@jzheaux ping? Any news on Spring Security 6?

@jankoh
Copy link
Author

jankoh commented Apr 13, 2023

@jzheaux still no answer at all? Will this be released as part of the next spring spring boot patch release?

@jankoh
Copy link
Author

jankoh commented Apr 24, 2023

Just checked: the fix is part of Spring Security 6.0.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: saml2 An issue in SAML2 modules status: duplicate A duplicate of another issue type: bug A general bug
Projects
None yet
Development

No branches or pull requests

2 participants