Loading Spring Webflux application in external iframe
Spring Boot version: 2.3.0.RELEASE
Using spring boot application as src
of iframe
with spring security in classpath, webflux and servlet app behaves differently.
Security config for reactive webapp:
@Configuration @EnableWebFluxSecurity public class SecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http .headers().frameOptions().disable() .and() .authorizeExchange() .anyExchange().authenticated() .and() .formLogin() .and() .build(); } }
Security config for servlet webapp:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.headers().frameOptions().disable() .and() .authorizeRequests() .anyRequest().authenticated() .and() .formLogin(); } }
Using tomcat server and security config as given above, user gets logged in and response is successfully sent back with 200 OK. Simliar config in webflux with netty server responds with 403 Forbidden and response as
CSRF Token has been associated to this client.
Perhaps it is related to Set-cookie with SameSite=Lax; in webflux.
Use iframe
within any external domain with src
set as spring boot app. Try deleting cookies if you are unable to regenerate the issue.
<iframe src="http://localhost:8080/"> </iframe>
Sample app – spring-iframe.zip
Use case: many Customer Relationship Management services integration requires app to open in their iframe, in this particular case this app is used in Salesforce integration.
Questions: Is there any way around to login in external iframe using spring webflux as dependency?
CookieWebSessionIdResolver
bean can be customized to use different options for session cookie. sameSite(null)
will remove "SameSite" attribute from cookie.
@Bean public WebSessionIdResolver webSessionIdResolver() { CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver(); resolver.setCookieName("SESSION"); resolver.addCookieInitializer((builder) -> { builder.path("/") .httpOnly(true) .secure(true) .sameSite(null); }); return resolver; }
Session configuration :
@Configuration @EnableSpringWebSession public class SessionConfig { @Bean public ReactiveSessionRepository<MapSession> sessionRepository() { return new ReactiveMapSessionRepository(new ConcurrentHashMap<>()); } @Bean public WebSessionIdResolver webSessionIdResolver() { CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver(); resolver.setCookieName("SESSION"); resolver.addCookieInitializer((builder) -> { builder.path("/") .httpOnly(true) .secure(true) .sameSite(null); }); return resolver; } }
Spring session-core dependency :
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-core</artifactId> <version>2.3.0.RELEASE</version> </dependency>