Handling SAML redirects to AJAX requests

I have several AngularJS applications using Spring / Java and SAML 2.0 for SSO (using the Spring Security SAML extension). My SSO identifier provider is OpenAM, and everything works very well. However, I am faced with a situation where the user performs a global exit from one application, but has other tabs. Since these are single page web applications, many functions can still be used on lost UNTIL tabs, the user does something to invoke the ajax request. Of course, these AJAX requests are intercepted by Spring SAML security filters and trigger an authentication attempt through REDIRECT to the OpenAM login URL. Of course, this leads to chaos in the browser, since redirects to another domain are not allowed in AJAX requests. In addition, I can’t do anything with Angular $ http interceptors, as requests are “canceled” and no quality information is available in the $ http error callback function (such as convenient status code 401/403). All I know is that the request failed.

I do not want to assume that all failed $ http requests are caused by authentication problems (and do $ window.location.reload ()), as there may be legitimate reasons for the failure. My preference is to suppress Spring's security redirects (to the OpenAM login page) for ajax requests and send status code 401/403 instead. This would allow me to handle the error in the $ http interceptor and perform a full page load if it is an authentication error, so it elegantly redirects to the login page, as if they were going to the site for the first time.

Any ideas on how to do this?

+5
source share
2 answers

The bean is responsible for initiating authentication and deciding whether to return an HTTP error, forwarding, ... is an instance of AuthenticationEntryPoint . To change its behavior, you can:

  • configure the current SAMLEntryPoint (extend the commence method) and override the default behavior in case of a request - call AJAX from Angular, so it returns an HTTP error instead of redirecting to IDP
  • or define another security:http element in your Spring context (up to the current one) that covers only your AJAX requests (for example, with the attribute pattern="/api/**" ) and uses an entry point that behaves the way you want (see Http403ForbiddenEntryPoint )
+4
source

Referring to the possible implementation of Vladimir the first bullet - taken from https://www.jasha.eu/blogposts/2015/10/saml-authentication-angularjs-spring-security.html

 public class XhrSamlEntryPoint extends SAMLEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { if (isXmlHttpRequest(request) && e instanceof InsufficientAuthenticationException) { response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); return; } super.commence(request, response, e); } private boolean isXmlHttpRequest(HttpServletRequest request) { return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With")); } } 

Remember that X-Requested-With is not a required header, so detection is not bulletproof according to this answer . In my case, since the server part was used with the SPA interface, I completely removed the ajax call check.

0
source

All Articles