I’m using OAuth2 to secure my vaadin app and have implemented this using spring security. However as stated in
Petters tutorial on filter based security . You should manually redirect back in case a push or heartbeat request is the first to go through.
The first one is the URL the user is redirected to after logging in. By default, Spring will save the URL the user originally tried to access and redirect the user back to that URL after authentication. In a Vaadin application, this URL might be a heartbeat or push URL on some occasions. If this happens, the user would only see a blank page and would have to manually change the URL in the browser to get back to the application.
An easy fix is to just permit all on both PUSH and HEARTBEAT urls like this:
So I wonder if this is in any way a security threat when using WEBSOCKET_XHR and if so, what is the best way to fix this. Note that since I use OAuth with an external server I cannot just change the redirect url.
The question is basically is there anything sensitive happening behind the /vaadinServlet/PUSH/** endpoint, because if it is, my implementation is bad. And I would need to find some other way to fix this…
I was able to pinpoint when the redirect occurs, and find a solution.
After successful login the OAuth2ClientAuthenticationProcessingFilter’s AuthenticationSuccessHandler deals with the redirect.
The redirect url comes from a HttpSessionRequestCache, and as @Peter Streef said sometimes this url contains Vaadin heartbeat or push.
The good news is that, there is a workaround. Just have to modify the request cache to return different SavedRequest when the url contains Vaadin push or heartbeat parameters. Unfortunately there is no easy way to extend the OAuth2ClientAuthenticationProcessingFilter functionality.
The only way I was able to do it, is this way:
in the WebSecurityConfigurerAdapter
@Override
public final void configure(WebSecurity web) throws Exception {
web.postBuildAction(() -> {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setRequestCache(new MyHttpSessionRequestCache());
try {
getAuthFilter().ifPresent(filter -> filter.setAuthenticationSuccessHandler(successHandler));
} catch (Exception e) {
//log
}
});
}
//Get the SecurityFilterChain and find the filter.
private Optional<OAuth2ClientAuthenticationProcessingFilter> getAuthFilter() throws Exception {
return getHttp().getObject().getFilters()
.stream()
.filter(f -> f.getClass().equals(OAuth2ClientAuthenticationProcessingFilter.class))
.map(OAuth2ClientAuthenticationProcessingFilter.class::cast)
.findFirst();
}
public class MyHttpSessionRequestCache extends HttpSessionRequestCache {
@Override
public SavedRequest getRequest(HttpServletRequest currentRequest, HttpServletResponse response) {
SavedRequest savedRequest = super.getRequest(currentRequest, response);
if ( savedRequest.getRedirectUrl().contains("/vaadinServlet") ) {
SimpleSavedRequest modifiedSavedRequest = new SimpleSavedRequest(savedRequest);
String redirectUrl = //set the required redirect url
modifiedSavedRequest.setRedirectUrl(redirectUrl);
return modifiedSavedRequest;
} else {
return savedRequest;
}
}
}
Maybe in the future there will be some mechanism to configure the OAuth2ClientAuthenticationProcessingFilter. Like with the UsernamePasswordAuthenticationFilter via http.formLogin()
An alternative solution would be to find where the “wrong” url is saved in the session, and alter it that point.
The attached Spring Security configuration will force redirection to “/” after successful sign-in. The part which follows after “/#!” will be preserved and you will get to the state you had tried to access before sing-in as Vaadin architecture is SPA.