samuelj
samuelj

Reputation: 135

Pentaho j_spring_security_check mixed content. HTTPS to HTTP

I have installed Pentaho (9.x) on Tomcat 8.5 and OpenJDK 1.8 as required. In front of it there is Apache 2.4 with mod_proxy_http.

My website is served with HTTPS and I have these Proxy rules:

    RequestHeader set X-Forwarded-Proto "https"
    ProxyPreserveHost on

    ProxyPass "/pentaho"  "http://tomcat_host_ip:8080/pentaho"
    ProxyPassReverse "/pentaho"  "http://tomcat_host_ip:8080/pentaho"

    ProxyPass "/pentaho/"  "http://tomcat_host_ip:8080/pentaho/"
    ProxyPassReverse "/pentaho/"  "http://tomcat_host_ip:8080/pentaho/"

    ProxyPass "/pentaho/Login"  "http://tomcat_host_ip:8080/pentaho/Login"
    ProxyPassReverse "/pentaho/Login"  "http://tomcat_host_ip:8080/pentaho/Login"

When I try to log in a get an error during the POST: https://pentaho.mywebsite.org/pentaho/j_spring_security_check

The application try to responde with HTTP protocol instead HTTPS.

In the request header I have the correct Referer and Origin: Origin: https://pentaho.mywebsite.org Referer: https://pentaho.mywebsite.org/pentaho/Login

But the response header reply with HTTP and NOT https: Location http://pentaho.mywebsite.org/pentaho/

Upvotes: 2

Views: 1034

Answers (2)

Piotr P. Karwasz
Piotr P. Karwasz

Reputation: 16165

Servlet applications use the scheme, serverName and serverPort properties of a ServletRequest to generate hyperlinks. Usually Tomcat gets the latter two from the Host request header, while scheme depends on the connector.

If you use a reverse proxy, the above logic may not be enough. You have two solution:

Setting scheme statically

In your case the proxy uses HTTPS, while Tomcat uses HTTP, so you must override the scheme and secure properties:

<Connector
    port="8080"
    scheme="https"
    secure="true"
    ...

while the Apache HTTP Server configuration can be shortened to:

ProxyPreserveHost on

ProxyPass "/pentaho"  "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho"  "http://tomcat_host_ip:8080/pentaho"

Remark that in your answer you didn't set the secure attribute: this attribute decides whether the transport is confidential. If you don't set it to true, Tomcat will automatically redirect the browser to redirectPort whenever the application asks for a confidential transport (cf. Securing Web Applications).

This solution only works correctly, if your proxy forwards only HTTPS requests to Tomcat.

Setting scheme dynamically

If you forward both HTTP and HTTPS requests to Tomcat, the server needs a way to distinguish between them. Therefore you need to add a RemoteIpValve to your Tomcat configuration:

<Valve className="org.apache.catalina.valves.RemoteIpValve" />
<Connector
    port="8080"
    redirectPort="443"
    ...

and ask Apache HTTP Server to add an X-Forwarded-Proto header:

RequestHeader set X-Forwarded-Proto "expr=%{REQUEST_SCHEME}"
ProxyPreserveHost on

ProxyPass "/pentaho"  "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho"  "http://tomcat_host_ip:8080/pentaho"

This solution has also the advantage to set the client's remoteHost and remoteAddr instead of those of the proxy.

Upvotes: 1

samuelj
samuelj

Reputation: 135

I solved the problem just adding proxyPort="443" and scheme="https" to my http connector in Tomcat.

The rule

RequestHeader set X-Forwarded-Proto "https"

on Apache was unusefull. This is my correct Apache configuration

ProxyPreserveHost on

ProxyPass "/pentaho"  "http://tomcat_host_ip:8080/pentaho"
ProxyPassReverse "/pentaho"  "http://tomcat_host_ip:8080/pentaho"

ProxyPass "/pentaho/"  "http://tomcat_host_ip:8080/pentaho/"
ProxyPassReverse "/pentaho/"  "http://tomcat_host_ip:8080/pentaho/"

And this is my Tomcat HTTP connector

   <Connector URIEncoding="UTF-8"
   port="8080" protocol="HTTP/1.1"
   connectionTimeout="20000"
   proxyPort="443"
   scheme="https"
   redirectPort="8443"
   relaxedPathChars="[]|"
   relaxedQueryChars="^{}[]|&amp;"
   maxHttpHeaderSize="65536"
   />

Upvotes: 3

Related Questions