title: Spring Boot with Spring Security behind Load Balancer: redirect HTTP to HTTPS
body: <p>I'm using Elastic Beanstalk to deploy a Spring Boot web server, running behind an application load balancer (Elastic Load Balancer). A business rule is that this web server should only be contacted through HTTPS. So any HTTP request must first be forwarded to HTTPS.</p>
  
  <p>Based on <a href="https://aws.amazon.com/premiumsupport/knowledge-center/redirect-http-https-elb/" rel="nofollow noreferrer">this</a> article from Amazon, I should simply inspect the <code>x-forwarded-for</code> and <code>x-forwarded-proto</code> headers, which are set by the load balancer. These headers contain information about the original request, made by the client to the load balancer.</p>
  
  <p>So I started looking for built-in ways for Spring Boot (I'm using the built-in Tomcat server, btw) to inspect those two headers and do the redirection, without having to write too much code myself. The Spring Boot (we're on version 1.4) <a href="https://docs.spring.io/spring-boot/docs/1.4.0.RELEASE/reference/htmlsingle/#howto-enable-https" rel="nofollow noreferrer">docs</a> state to use the following application properties:</p>
  
  <pre><code>security.require_ssl=true
  server.tomcat.remote_ip_header=x-forwarded-for
  server.tomcat.protocol_header=x-forwarded-proto
  </code></pre>
  
  <p>Testing this with Postman gives me an HTTP 200 where I should be getting a 301/302 redirect. I suspect this is due to me using Spring Security. To make it work with Spring Security, I could add this to my <code>WebSecurityConfigurerAdapter</code>:</p>
  
  <pre><code> http.requiresChannel().anyRequest().requiresSecure();
  </code></pre>
  
  <p>But now my headers are ignored and <em>all</em> requests are forwarded to HTTPS, even if the original request <em>was HTTPS already</em>. So now nothing works.</p>
  
  <p>The answer by Rodrigo Quesada <a href="https://stackoverflow.com/questions/26655875/spring-boot-redirect-http-to-https">here</a> seems to be what I need, but it still doesn't respect my headers, for some reason. This request still gives me a redirect instead of a 200:</p>
  
  <pre><code>GET / HTTP/1.1
  Host: localhost:8080
  X-Forwarded-Proto: https
  X-Forwarded-For: 192.168.0.30
  </code></pre>
  
  <p>There are many other solutions here and on other websites, using another intermediary web server, or configuring NGINX or Apache on AWS to do the redirection. But I'm using Tomcat already, why would I want to configure <em>yet another</em> web server.</p>
  
  <p>So how can I actually configure Spring Boot/Tomcat/Spring Security in a Spring-way to do this redirection? Is there a way to extend the behavior of the <code>requiresSecure()</code> function so that it takes into account my request headers? Or even better, are there any Spring Security alternatives to the application properties I tried?</p>