Uploaded image for project: 'Tapestry 5'
  1. Tapestry 5
  2. TAP5-2577

HTTPS + Load balancer not working with InjectPage or Class

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 5.4.1, 5.4.2
    • Fix Version/s: None
    • Component/s: tapestry-core
    • Labels:

      Description

      I have a secured application, meaning it insists on HTTPS, so it should return HTTPS URLs for everything, but it doesn't. When an event handler returns a page class or an injected page, Tapestry returns an HTTP URL.

      public class Page1 {
      
      	@InjectPage
      	private Page2 page2;
      
      	Object onToPage2InjectPage() {
      		return page2;
      	}
      
      	Object onToPage2Class() {
      		return Page2.class;
      	}
      
      }
      

      The problem started when I switched handling of HTTPS to a load balancer (AWS Application Load Balancer). It forwards the request as HTTP, along with the HTTPS headers intact. Normally Tapestry recognises the request is secure and returns a secure URL, but not in the 2 cases above.

      I've narrowed the problem down to a method in RequestSecurityManagerImpl:

          public LinkSecurity checkPageSecurity(String pageName)
          {
              if (!securityEnabled)
              {
                  return request.isSecure() ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
              }
      
              boolean securePage = isSecure(pageName);
      
              if (request.isSecure() == securePage)
              {
                  return securePage ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
              }
      
              // Return a value that will, ultimately, force an absolute URL.
      
              return securePage ? LinkSecurity.FORCE_SECURE : LinkSecurity.FORCE_INSECURE;
          }
      

      It assumes that a secure page is HTTPS and therefore it returns LinkSecurity.SECURE instead of LinkSecurity.FORCE_SECURE . Consequently, Tapestry returns a relative URL instead of an absolute URL specifying "https://".

      I see 3 possible solutions:

      (1) Always return absolute URLs.
      (2) Instead of relative URLs, return a protocol-relative URL (i.e. "//" instead of "https://" or "http://").
      (3) Modify the code to handle the possibility that protocol and isSecure() disagree. For example (this code snippet has been tested and is running live):

              if (request.isSecure() == securePage) 
              {
                  if (request.isSecure() && request.getAttribute("servletAPI.scheme").equals("https")
      	        || !request.isSecure() && request.getAttribute("servletAPI.scheme").equals("http")) 
                  {
                          return securePage ? LinkSecurity.SECURE : LinkSecurity.INSECURE;
                  }
                  else 
                  {
                      return securePage ? LinkSecurity.FORCE_SECURE : LinkSecurity.FORCE_INSECURE;
                  }
              }
      

      Is possibility 1 a bad idea? Are longer URLs really a big deal?

      Some people suggest possibility 2 has downsides such as page URLs not standing on their own if copied and pasted. Maybe that's an issue.

      I used possibility 3 to solved my problem. It works.

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              geoffcallender Geoff Callender
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated: