Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the Spring `SavedRequest` include any cleanup logic to avoid redirect loops or similar?

I'm using the SavedRequest to redirect the user to the originally requested URL after login.

I get the url like this:

public String requestedUrl(HttpServletRequest request, HttpServletResponse response) {
        SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
        if (savedRequest != null) {
            return savedRequest.getRedirectUrl();
        }
        return "";
}

I wonder if it is worth to check on that URL, if for example

  • the base-path is corresponding to the configured application base path (for security reasons)
  • the path is not redirecting to /login or some other urls which might cause an infinite redirect loop

Does the SavedRequest do any cleanup similar to this? If yes, which exactly?

like image 508
LukeSolar Avatar asked Jul 18 '19 17:07

LukeSolar


People also ask

What is authentication manager in Spring Security?

In Spring Security, the authentication manager assumes the job of establishing a user's identity. An authentication manager is defined by the org. springframework. security.

What is UsernamePasswordAuthenticationToken Spring Security?

The UsernamePasswordAuthenticationToken is an implementation of interface Authentication which extends the interface Principal . Principal is defined in the JSE java. security . UsernamePasswordAuthenticationToken is a concept in Spring Security which implements the Principal interface.

How does Spring Security work?

The short answer: At its core, Spring Security is really just a bunch of servlet filters that help you add authentication and authorization to your web application. It also integrates well with frameworks like Spring Web MVC (or Spring Boot), as well as with standards like OAuth2 or SAML.


1 Answers

This is not an answer and is based on a survey of the code because I'm curious. :3

Let me begin by saying that it would be useful to know how you've configured Spring Security in your project to actually get the root of your problem. As you trace up from SavedRequest to see how it's used in Spring Security a lot of possible avenues open up regarding how everything is wired up and configured at the beginning.

As the preceding notes, the code directly adjacent to SavedRequest itself is so simple that it is generally unrelated to the root of your problem. Your question's focus could be broadened: "Does Spring Security avoid redirect loops to /login when applying SavedRequests?"

I think the docs 10.1.4 Request Matching and HttpFirewall do address your question regarding the base path:

The Servlet Specification defines several properties for the HttpServletRequest which are accessible via getter methods, and which we might want to match against. These are the contextPath, servletPath, pathInfo and queryString. Spring Security is only interested in securing paths within the application, so the contextPath is ignored.

Emphasis mine.

In a default configuration it appears that DefaultSavedRequest will be the implementation of SavedRequest in use according to HttpSessionRequestCache.

DefaultSavedRequest has not undergone any extensive changes since you originally asked your question.

Establishing that, we can say that the implementation of the class is fairly straightforward, is very bean-like and limits itself to saving the request as presented. It performs no analysis during construction, other than to exclude certain headers ("Skip If-Modified-Since and If-None-Match header").

public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver) {
    Assert.notNull(request, "Request required");
    Assert.notNull(portResolver, "PortResolver required");

    // Cookies
    addCookies(request.getCookies());

    // Headers
    Enumeration<String> names = request.getHeaderNames();

    while (names.hasMoreElements()) {
        String name = names.nextElement();
        // Skip If-Modified-Since and If-None-Match header. SEC-1412, SEC-1624.
        if (HEADER_IF_MODIFIED_SINCE.equalsIgnoreCase(name)
                || HEADER_IF_NONE_MATCH.equalsIgnoreCase(name)) {
            continue;
        }
        Enumeration<String> values = request.getHeaders(name);

        while (values.hasMoreElements()) {
            this.addHeader(name, values.nextElement());
        }
    }

    // Locales
    addLocales(request.getLocales());

    // Parameters
    addParameters(request.getParameterMap());

    // Primitives
    this.method = request.getMethod();
    this.pathInfo = request.getPathInfo();
    this.queryString = request.getQueryString();
    this.requestURI = request.getRequestURI();
    this.serverPort = portResolver.getServerPort(request);
    this.requestURL = request.getRequestURL().toString();
    this.scheme = request.getScheme();
    this.serverName = request.getServerName();
    this.contextPath = request.getContextPath();
    this.servletPath = request.getServletPath();
}

addCookies, addHeader, addLocales and addParameters are similarly simple. This class doesn't resolve requests to guard against infinite redirects or even check its base path.

Therefore we'll cast the net further to find another suspect. Next up is HttpSessionRequestCache. The bean can be created in a variety of ways based on your usage of Spring Security so things kind of spiral out from there HttpConfigurationBuilder / HttpSecurity / RequestCacheConfigurer; an expert+more information from you would indeed be welcome!

like image 83
Jon Sampson Avatar answered Oct 09 '22 01:10

Jon Sampson