Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-16262

spring-web CORS requires X-Forwarded-Port

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Minor
    • Resolution: Complete
    • Affects Version/s: 4.3.12
    • Fix Version/s: 4.3.14, 5.0.3
    • Component/s: Web
    • Labels:
      None
    • Last commented by a User:
      true

      Description

      I am running a spring-boot app within Google AppEngine behind an IAP proxy which terminates https connections. The proxy sets X-Forwarded-Proto=https on requests, but does not set X-Forwarded-Port. The result is that the spring-web CORS filter rejects requests with "not same origin" even though the origin actually is the same.

      This is made worse by the fact that the Chrome browser sends the "origin" header on many different request types, including all POST requests and all resources referenced from a css-file (eg fonts) - ie on requests which are NOT cross-origin.

      While it may be argued that Google should add a header, this is a problem that may hit many users. It is also really really nasty to actually figure out the real cause of the problem..

        Issue Links

          Activity

          Hide
          simon-um simon Kitching added a comment -

          Class UriComponentsBuilder has separate fields for port and scheme. Method UriComponentsBuilder.adaptFromForwardedHeaders checks for "X-Forwarded-*" headers and modifies those fields. However when X-Forwarded-Proto is present then ONLY field "scheme" is updated, not field "port". The result is that a request which has been forwarded by the Google IAP proxy, and thus has X-Forwarded-Proto but not X-Forwarded-Port, has the original "https" scheme but port 80.

          Method WebUtils.isSameOrigin calls getPort() which returns port 80 for the incoming request, but deduces port 443 from the "origin" http header, and thus rejects the incoming request.

          I think a good argument could be made for method adaptFromForwardedHeaders to set field port (in same way as WebUtils.getPort) when X-Forwarded-Proto is present.

          At the very least, please add some suitable logging to indicate this problem - it has sucked up 2 days of my time tracking this down. In particular, this only occurs behind a proxy - local testing shows no problem.

          Show
          simon-um simon Kitching added a comment - Class UriComponentsBuilder has separate fields for port and scheme. Method UriComponentsBuilder.adaptFromForwardedHeaders checks for "X-Forwarded-*" headers and modifies those fields. However when X-Forwarded-Proto is present then ONLY field "scheme" is updated, not field "port". The result is that a request which has been forwarded by the Google IAP proxy, and thus has X-Forwarded-Proto but not X-Forwarded-Port, has the original "https" scheme but port 80. Method WebUtils.isSameOrigin calls getPort() which returns port 80 for the incoming request, but deduces port 443 from the "origin" http header, and thus rejects the incoming request. I think a good argument could be made for method adaptFromForwardedHeaders to set field port (in same way as WebUtils.getPort) when X-Forwarded-Proto is present. At the very least, please add some suitable logging to indicate this problem - it has sucked up 2 days of my time tracking this down. In particular, this only occurs behind a proxy - local testing shows no problem.
          Hide
          simon-um simon Kitching added a comment -

          As mentioned in https://github.com/spring-projects/spring-boot/issues/10965, Traefik is another proxy which fails to set X-Forwarded-Port.

          Show
          simon-um simon Kitching added a comment - As mentioned in https://github.com/spring-projects/spring-boot/issues/10965 , Traefik is another proxy which fails to set X-Forwarded-Port.
          Hide
          simon-um simon Kitching added a comment -

          For anyone else looking for a solution for this problem, I have implemented a single-class workaround documented here: http://moi.vonos.net/java/spring-forward/
          Basically, it provides a ServletFilter which sets header X-Forwarded-Port=443 if X-Forwarded-Proto="https", and solves the problem for me behind Google IAP.

          Show
          simon-um simon Kitching added a comment - For anyone else looking for a solution for this problem, I have implemented a single-class workaround documented here: http://moi.vonos.net/java/spring-forward/ Basically, it provides a ServletFilter which sets header X-Forwarded-Port=443 if X-Forwarded-Proto="https", and solves the problem for me behind Google IAP.
          Hide
          sdeleuze Sébastien Deleuze added a comment -

          I will shortly merge this pull-request after some remaining polish. Feel free to have a look.

          Show
          sdeleuze Sébastien Deleuze added a comment - I will shortly merge this pull-request after some remaining polish. Feel free to have a look.
          Hide
          sdeleuze Sébastien Deleuze added a comment -

          Commits merged in both 4.3.x and master branches, with additional optimizations on master.

          Show
          sdeleuze Sébastien Deleuze added a comment - Commits merged in both 4.3.x and master branches, with additional optimizations on master.

            People

            • Assignee:
              sdeleuze Sébastien Deleuze
              Reporter:
              simon-um simon Kitching
              Last updater:
              Sébastien Deleuze
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                1 week ago