<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Play!Framework Archives | Clever Cloud</title>
	<atom:link href="https://www.clever.cloud/blog/tag/playframework/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.clever.cloud/blog/tag/playframework/</link>
	<description>From Code to Product</description>
	<lastBuildDate>Tue, 01 Dec 2015 17:55:00 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://cdn.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>Play!Framework Archives | Clever Cloud</title>
	<link>https://www.clever.cloud/blog/tag/playframework/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to Redirect to HTTPS With Play 2.4</title>
		<link>https://www.clever.cloud/blog/engineering/2015/12/01/redirect-to-https-in-play/</link>
		
		<dc:creator><![CDATA[Julien Durillon]]></dc:creator>
		<pubDate>Tue, 01 Dec 2015 17:55:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Play!Framework]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[SSL]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2015/12/01/redirect-to-https-in-play/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="ssl post 1" decoding="async" fetchpriority="high" srcset="https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-1368x528.jpg 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>To protect your web app or API, there is almost only one way at this time: TLS. But users and browsers don&#39;t always use TLS by default. So what you want is to redirect them to a TLS encrypted version of your site if they try to connect via plain http.</p>
<span id="more-2803"></span>
<p>Here is how to do it with Play Framework 2.4 in scala:</p>
<h2 id="play-and-http-filters">Play! and HTTP filters</h2>
<p>We will start by creating a &quot;TLSFilter.scala&quot; file and write a TLSFilter class in it:</p>
<pre><code class="language-scala">class TLSFilter extends Filter {
  def apply(nextFilter: RequestHeader =&gt; Future[Result])
    (requestHeader: RequestHeader): Future[Result] = {
      if(!requestHeader.secure)
        Future.successful(Results.MovedPermanently(&quot;https://&quot; + requestHeader.host + requestHeader.uri))
      else
        nextFilter(requestHeader).map(_.withHeaders(&quot;Strict-Transport-Security&quot; -&gt; &quot;max-age=31536000; includeSubDomains&quot;))
  }
}
</code></pre>
<p>This part is easy: we implement the apply function by just checking the <code>secure</code> value of <code>RequestHeader</code>. If the connection is not <em>secure</em>, we need to redirect the client to the same url only with &quot;https&quot; as the protocol. If the connection is <em>secure</em>, we pass the request to the next header. Nothing simpler.</p>
<p>Note that we use <code>requestHeader.host</code> instead of <code>requestHeader.domain</code> because the <code>host</code> value is actually the value of the <code>Host</code> header as set by the client, with optional port and stuff.</p>
<p>Note that we create a <code>Filter</code> implementation and not an <code>EssentialFilter</code> one because we do not care about the body.</p>
<p>Next, you need to create a <code>HttpFilters</code> implementation that will hold the instance of your <code>TLSFilter</code>:</p>
<pre><code class="language-scala">// In TLSFilter.scala
class MyFilters extends HttpFilters {
  val filters = Seq(new TLSFilter)
}
</code></pre>
<p>And finally, you need to tell Play! to use your <code>Filters</code> class:</p>
<pre><code class="language-properties"># In conf/application.conf
play.http.filters=my.package.MyFilters
</code></pre>
<p>Now it will check your requests and permamently redirect the clients to HTTPS.</p>
<p>But, how does Play! know that the request is <em>secure</em>?</p>
<h2 id="reverse-proxies-where-did-the-s-go">Reverse proxies: where did the &#39;s&#39; go?</h2>
<p>Now, we need to ensure that Play! knows to differentiate a secured connection from a plain one. If you configured HTTPS in your application, it&#39;s quite simple to understand. But it is not always the case:</p>
<p>You most probably did <em>not</em>, configure TLS in your application. And <em>that</em> is because <em>you deployed it on a very powerful and developer-friendly PaaS</em>. So, chances are your Play! application is getting requests in plain HTTP, because the TLS encryption ended at the front reverse-proxy that&#39;s piping the request towards your app.</p>
<p>How then is your application going to know that the connection is secured? Enter the non-standard and the standard ways.</p>
<h3 id="x-forwarded-proto">X-Forwarded-Proto</h3>
<p>The first, non-standard but widely used (e.g. at Clever Cloud) way to know if the request handled by the reverse proxy in front came in a secure channel is to check the <code>X-Forwarded-Proto</code> HTTP header. Like all non-standard headers, you can recognize it by the <code>X-</code> at the beginning of the name.</p>
<p>This header describes how the final client is communicating with the reverse-proxy.</p>
<p>It takes two values: <strong>http</strong> and <strong>https</strong>. You can check for that header in your application. But we will see below that Play! can do it by itself.</p>
<h3 id="rfc-2739">RFC 2739</h3>
<p>Also called the <em>Forwarded HTTP Extension</em>, it standardize the way that a proxy tells the final endpoint what is going on between the final client and itself. It&#39;s been published in June 2014.</p>
<p>You can read it here: <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>. But the only thing that is relevant for us is the <code>proto</code> parameter. Like <code>X-Forwarded-Proto</code> earlier, its values that interest us are <strong>http</strong> and <strong>https</strong>. Like for the other one, Play! can handle those values for you, if you ask nicely.</p>
<h2 id="how-to-make-play-handle-forwarded-headers">How to make Play! handle Forwarded headers?</h2>
<p>At the time of this writing, Play! framework support for <code>Forwarded</code> headers have known many states:</p>
<ul>
<li>In Play! 1.x, you need to add <code>XForwardedSupport=all</code> in your application.conf</li>
<li>In Play! 2.0 to 2.3, you need to add <code>trustxforwarded=true</code> in your application.conf</li>
</ul>
<p>Both these ways only support the <code>X-Forwarded-Proto</code> header.</p>
<p>Now, in Play! 2.4.x, the philosophy is different:</p>
<ul>
<li>Define the version of the Forwarded header you want to use: <code>play.http.forwarded.version=x-forwarded|rfc7239</code></li>
<li>Set the proxies you trust: <code>play.http.forwarded.trustedProxies=[&quot;proxy_ip1&quot;,&quot;proxy_ip2&quot;,…]</code>.</li>
</ul>
<p>Of course <code>proxy_ipX</code> can be an actual IP or a subnet mask, like &quot;0.0.0.0&quot; or &quot;::&quot; to trust every IPv4 or v6, respectively. Defaults are &quot;127.0.0.1&quot; and &quot;::FF&quot;.</p>
<p>Also, as the <code>X-Forwarded-Proto</code> header is the one that is widely used in the world, the <code>version</code> default value is &quot;x-forwarded&quot;.</p>
<h2 id="what-the-hell-is-strict-transport-security">What the hell is Strict-Transport-Security?</h2>
<p>As you read the filter code, you must have seen that in the case the request is already in HTTPS, we still add a header to the response: <code>Strict-Transport-Security: max-age=31536000</code>.</p>
<p>This is the HTTP Strict Transport Security (HSTS) header. What it does is basically telling the client (most likely a browser): &quot;Next time (and for the next 31536000 seconds), if your user tries to load the unencrypted version of the site, don&#39;t wait for me to redirect you and use https already&quot;.</p>
<p>The browser (meaning: chrome &gt;= 4.0.211.0, firefox &gt;= 4.0, Opera &gt;= 12, IE &gt;= 11) will then save the website and automatically replace &quot;http&quot; by &quot;https&quot; in the requests the next times.</p>
<p>This mechanism is documented here: <a href="https://www.rfc-editor.org/rfc/rfc6797.txt">https://www.rfc-editor.org/rfc/rfc6797.txt</a>.</p>
<p>You <em>MUST</em> set the <code>max-age</code> value. You can also add <code>includeSubDomains</code> (after a &quot;;&quot; of course), which means &quot;if you get that header while requesting domain.com, please use HTTPS when requesting *.domain.com too&quot;. It is a good practice to always add <code>includeSubDomains</code> just in case.</p>
<p>Please note that the STS header can only be set if the website is already TLS protected. You <em>MUST NOT</em> set this header on a non-TLS response.</p>
<p>If you want the browsers to use HSTS before the first request, you can register your domain to be included in browsers <em>preload lists</em>. To achieve that, register your domain here: <a href="https://hstspreload.appspot.com/">https://hstspreload.appspot.com/</a>. Also add the <code>preload</code> value to the header, like that: <code>Strict-Transport-Security: max-age=31536000; preload</code>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="ssl post 1" decoding="async" srcset="https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1.jpg 1400w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-300x116.jpg 300w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-1024x395.jpg 1024w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-768x296.jpg 768w, https://cdn.clever-cloud.com/uploads/2021/08/ssl-post-1-1368x528.jpg 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>To protect your web app or API, there is almost only one way at this time: TLS. But users and browsers don&#39;t always use TLS by default. So what you want is to redirect them to a TLS encrypted version of your site if they try to connect via plain http.</p>
<span id="more-2803"></span>
<p>Here is how to do it with Play Framework 2.4 in scala:</p>
<h2 id="play-and-http-filters">Play! and HTTP filters</h2>
<p>We will start by creating a &quot;TLSFilter.scala&quot; file and write a TLSFilter class in it:</p>
<pre><code class="language-scala">class TLSFilter extends Filter {
  def apply(nextFilter: RequestHeader =&gt; Future[Result])
    (requestHeader: RequestHeader): Future[Result] = {
      if(!requestHeader.secure)
        Future.successful(Results.MovedPermanently(&quot;https://&quot; + requestHeader.host + requestHeader.uri))
      else
        nextFilter(requestHeader).map(_.withHeaders(&quot;Strict-Transport-Security&quot; -&gt; &quot;max-age=31536000; includeSubDomains&quot;))
  }
}
</code></pre>
<p>This part is easy: we implement the apply function by just checking the <code>secure</code> value of <code>RequestHeader</code>. If the connection is not <em>secure</em>, we need to redirect the client to the same url only with &quot;https&quot; as the protocol. If the connection is <em>secure</em>, we pass the request to the next header. Nothing simpler.</p>
<p>Note that we use <code>requestHeader.host</code> instead of <code>requestHeader.domain</code> because the <code>host</code> value is actually the value of the <code>Host</code> header as set by the client, with optional port and stuff.</p>
<p>Note that we create a <code>Filter</code> implementation and not an <code>EssentialFilter</code> one because we do not care about the body.</p>
<p>Next, you need to create a <code>HttpFilters</code> implementation that will hold the instance of your <code>TLSFilter</code>:</p>
<pre><code class="language-scala">// In TLSFilter.scala
class MyFilters extends HttpFilters {
  val filters = Seq(new TLSFilter)
}
</code></pre>
<p>And finally, you need to tell Play! to use your <code>Filters</code> class:</p>
<pre><code class="language-properties"># In conf/application.conf
play.http.filters=my.package.MyFilters
</code></pre>
<p>Now it will check your requests and permamently redirect the clients to HTTPS.</p>
<p>But, how does Play! know that the request is <em>secure</em>?</p>
<h2 id="reverse-proxies-where-did-the-s-go">Reverse proxies: where did the &#39;s&#39; go?</h2>
<p>Now, we need to ensure that Play! knows to differentiate a secured connection from a plain one. If you configured HTTPS in your application, it&#39;s quite simple to understand. But it is not always the case:</p>
<p>You most probably did <em>not</em>, configure TLS in your application. And <em>that</em> is because <em>you deployed it on a very powerful and developer-friendly PaaS</em>. So, chances are your Play! application is getting requests in plain HTTP, because the TLS encryption ended at the front reverse-proxy that&#39;s piping the request towards your app.</p>
<p>How then is your application going to know that the connection is secured? Enter the non-standard and the standard ways.</p>
<h3 id="x-forwarded-proto">X-Forwarded-Proto</h3>
<p>The first, non-standard but widely used (e.g. at Clever Cloud) way to know if the request handled by the reverse proxy in front came in a secure channel is to check the <code>X-Forwarded-Proto</code> HTTP header. Like all non-standard headers, you can recognize it by the <code>X-</code> at the beginning of the name.</p>
<p>This header describes how the final client is communicating with the reverse-proxy.</p>
<p>It takes two values: <strong>http</strong> and <strong>https</strong>. You can check for that header in your application. But we will see below that Play! can do it by itself.</p>
<h3 id="rfc-2739">RFC 2739</h3>
<p>Also called the <em>Forwarded HTTP Extension</em>, it standardize the way that a proxy tells the final endpoint what is going on between the final client and itself. It&#39;s been published in June 2014.</p>
<p>You can read it here: <a href="https://tools.ietf.org/html/rfc7239">https://tools.ietf.org/html/rfc7239</a>. But the only thing that is relevant for us is the <code>proto</code> parameter. Like <code>X-Forwarded-Proto</code> earlier, its values that interest us are <strong>http</strong> and <strong>https</strong>. Like for the other one, Play! can handle those values for you, if you ask nicely.</p>
<h2 id="how-to-make-play-handle-forwarded-headers">How to make Play! handle Forwarded headers?</h2>
<p>At the time of this writing, Play! framework support for <code>Forwarded</code> headers have known many states:</p>
<ul>
<li>In Play! 1.x, you need to add <code>XForwardedSupport=all</code> in your application.conf</li>
<li>In Play! 2.0 to 2.3, you need to add <code>trustxforwarded=true</code> in your application.conf</li>
</ul>
<p>Both these ways only support the <code>X-Forwarded-Proto</code> header.</p>
<p>Now, in Play! 2.4.x, the philosophy is different:</p>
<ul>
<li>Define the version of the Forwarded header you want to use: <code>play.http.forwarded.version=x-forwarded|rfc7239</code></li>
<li>Set the proxies you trust: <code>play.http.forwarded.trustedProxies=[&quot;proxy_ip1&quot;,&quot;proxy_ip2&quot;,…]</code>.</li>
</ul>
<p>Of course <code>proxy_ipX</code> can be an actual IP or a subnet mask, like &quot;0.0.0.0&quot; or &quot;::&quot; to trust every IPv4 or v6, respectively. Defaults are &quot;127.0.0.1&quot; and &quot;::FF&quot;.</p>
<p>Also, as the <code>X-Forwarded-Proto</code> header is the one that is widely used in the world, the <code>version</code> default value is &quot;x-forwarded&quot;.</p>
<h2 id="what-the-hell-is-strict-transport-security">What the hell is Strict-Transport-Security?</h2>
<p>As you read the filter code, you must have seen that in the case the request is already in HTTPS, we still add a header to the response: <code>Strict-Transport-Security: max-age=31536000</code>.</p>
<p>This is the HTTP Strict Transport Security (HSTS) header. What it does is basically telling the client (most likely a browser): &quot;Next time (and for the next 31536000 seconds), if your user tries to load the unencrypted version of the site, don&#39;t wait for me to redirect you and use https already&quot;.</p>
<p>The browser (meaning: chrome &gt;= 4.0.211.0, firefox &gt;= 4.0, Opera &gt;= 12, IE &gt;= 11) will then save the website and automatically replace &quot;http&quot; by &quot;https&quot; in the requests the next times.</p>
<p>This mechanism is documented here: <a href="https://www.rfc-editor.org/rfc/rfc6797.txt">https://www.rfc-editor.org/rfc/rfc6797.txt</a>.</p>
<p>You <em>MUST</em> set the <code>max-age</code> value. You can also add <code>includeSubDomains</code> (after a &quot;;&quot; of course), which means &quot;if you get that header while requesting domain.com, please use HTTPS when requesting *.domain.com too&quot;. It is a good practice to always add <code>includeSubDomains</code> just in case.</p>
<p>Please note that the STS header can only be set if the website is already TLS protected. You <em>MUST NOT</em> set this header on a non-TLS response.</p>
<p>If you want the browsers to use HSTS before the first request, you can register your domain to be included in browsers <em>preload lists</em>. To achieve that, register your domain here: <a href="https://hstspreload.appspot.com/">https://hstspreload.appspot.com/</a>. Also add the <code>preload</code> value to the header, like that: <code>Strict-Transport-Security: max-age=31536000; preload</code>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
