wilx
wilx

Reputation: 18228

Jetty, isSecure() returning false on HTTPS connection

I have hit a problem with isSecure() returning false on request arriving on HTTPS connection, actually a HTTPS connection with valid certificates from common CA, both user and server certificates. Why?

Here is a callstack:

callstack

But the member that is returned by isSecure() is false:

enter image description here

This is with Jetty 9.4.8.

UPDATE

On HttpChannelOverHttp(HttpChannel).onRequest(MetaData$Request) line: 638 I see _request.setSecure(HttpScheme.HTTPS.is(request.getURI().getScheme())); which could set up the flag to true. Unfortunately, the URI is incomplete of //host.name:8081/path/a/b/c format and getScheme() returns null which results in false being returned by is(). WTH?

UPDATE 2

It appears that I can fix this by adding the following to HttpConfiguration in jetty-config.xml:

                <Call name="addCustomizer">
                  <Arg>
                      <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
                  </Arg>
                </Call>

But it is unclear to my why is this necessary and why it does not work OOTB.

Upvotes: 1

Views: 1828

Answers (1)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49452

As you have discovered yourself, you were missing a configuration.

The fact that you felt you needed to manually add this configuration tells me you are using an old version of Jetty. (please consider upgrading, it is easier to control this now, as evidenced below)

The SecureRequestCustomizer in the HttpConfiguration is responsible for handling the identification of SSL Certificates, SNI, Host checks, the various HttpServletRequest attributes for SSL/TLS, etc..

It looks like this on older versions of Jetty.

<Call name="addCustomizer">
  <Arg>
    <New class="org.eclipse.jetty.server.SecureRequestCustomizer" />
  </Arg>
</Call>

On Newer versions of Jetty this is added by the jetty-ssl.xml xml (part of the ssl module), and it looks like this ...

<Configure id="Server" class="org.eclipse.jetty.server.Server">

  <!-- [snip] ssl connector setup -->

  <!-- =========================================================== -->
  <!-- Create a TLS specific HttpConfiguration based on the        -->
  <!-- common HttpConfiguration defined in jetty.xml               -->
  <!-- Add a SecureRequestCustomizer to extract certificate and    -->
  <!-- session information                                         -->
  <!-- =========================================================== -->
  <New id="sslHttpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
    <Arg><Ref refid="httpConfig"/></Arg>
    <Call name="addCustomizer">
      <Arg>
        <New class="org.eclipse.jetty.server.SecureRequestCustomizer">
          <Arg name="sniHostCheck" type="boolean"><Property name="jetty.ssl.sniHostCheck" default="true"/></Arg>
          <Arg name="stsMaxAgeSeconds" type="int"><Property name="jetty.ssl.stsMaxAgeSeconds" default="-1"/></Arg>
          <Arg name="stsIncludeSubdomains" type="boolean"><Property name="jetty.ssl.stsIncludeSubdomains" default="false"/></Arg>
        </New>
      </Arg>
    </Call>
  </New>

</Configure>

The reason this isn't on by default is that a request can be considered secure without Jetty handling the actual SSL/TLS. This is the forwarded scenario, from a load balancer, proxy, firewall, gateway, etc... In that scenario, the SSL/TLS is handled by another process, which talks to Jetty via a non-secure channel (standard HTTP without encryption, proxy, unix sockets, etc). The fact that the connection is secure or not is then communicated to jetty via "forwarded" headers.

This forwarded behavior is controlled by a different customizer org.eclipse.jetty.server.ForwardedRequestCustomizer (found in jetty-http-forwarded.xml, which part of the http-forwarded module)

Upvotes: 1

Related Questions