Acme-CPANModulesBundle-Import-MojoliciousAdvent-2017

 view release on metacpan or  search on metacpan

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

              <section id="section-1">
                  <p>As you all know, HTTP is a stateless protocol.
In Mojolicious applications the session is used to maintain state between requests.
These sessions are managed by the application&#39;s <a href="http://mojolicious.org/perldoc/Mojolicious/#sessions">session manager</a>.</p>

<p>During each request, the <a href="http://mojolicious.org/perldoc/Mojolicious/Controller#session">session</a> is just another hash reference attached to the controller, in some ways like the <a href="/blog/2017/12/02/day-2-the-stash">stash</a>, exc...
Mojolicious does this by encoding the structure, first as JSON then Base64.
It then signs the resulting string using HMAC-SHA1 and the application&#39;s <a href="http://mojolicious.org/perldoc/Mojolicious#secrets">secret</a> to prevent tampering and stores it as a cookie on the response to the client.</p>

<p>On subsequent requests, the client sends the cookie along with the request (as cookies do).
Mojolicious then checks if the document and signature validate against the secret, if so the cookie is decoded and made available again via the session method.</p>

<p>Two important things to note.
First, though the data is safe from tampering, it isn&#39;t encrypted; a savvy user can decode the cookie and see the stored data, so don&#39;t put anything in it that shouldn&#39;t be seen.
Second, this is only useful if the secret is strong and safe.
If not, the client could forge a cookie that appeared to come from your application, possibly with catastrophic results!
So while Mojolicious makes it easy, a little care can go a long way toward keeping your session data safe and trusted.</p>

              </section>
              <section id="section-2">
                  <h2>A Simple Session Example</h2>

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

</code></pre>

<p>When you run this application</p>

<pre><code>$ perl myapp.pl daemon
</code></pre>

<p>and visit <code>localhost:3000</code> you should see a counter that increments on each request.
That data is stored on the client (e.g. in the browser) between each request and is incremented on the server before sending it back to the client.
Each response is a new cookie with the new session data and a new cookie expiration time, <a href="http://mojolicious.org/perldoc/Mojolicious/Sessions#default_expiration">defaulting to one hour</a> from issue.
This also therefore implies that as long as you visit often enough (before any one cookie expires) and your data continues to validate against the secret, your session can last forever.</p>

<h2>Secret Security</h2>

<p>Now, one other thing you should see is that in your application&#39;s log output, you should have a message like</p>

<pre><code>Your secret passphrase needs to be changed
</code></pre>

<p>This happens because you are using the default secret for the application.
This default is just the name of the script, as you can see via the <a href="/blog/2017/12/05/day-5-your-apps-built-in-commands">eval command</a></p>

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN


</code></pre>

<p>If it finds a <code>secrets</code> parameter in your configuration, it will set it as the <code>secrets</code> on your application.
Since you have one in your new configuration file, it should set that property and the warning should go away.
Congratulations, you have a safer application already!</p>

<p>If sometime later, you suspect that someone has guessed your secret, or if your secret leaks out, you can change that secret and restart your application.
This will protect your application from malicious users.</p>

<p>For your clients, this will have the jarring effect that all existing sessions will be invalidated.
In the example application the counter would be reset.
If instead the session were being used to keep users logged in, they would suddenly be logged out.
If it was for tracking a shopping cart ... no more shopping cart.</p>

<p>This can actually be useful even if your secret is safe but you want to force-invalidate sessions for some other reason, like say your application was generating corrupt data or worse.
Generally, however, this is something you&#39;d like to avoid.</p>

<h2>A Random Secret?</h2>

<p>Now perhaps you are asking yourself, if Mojolicious knows I&#39;m using the insecure default couldn&#39;t it just set a random secret?
Sure, and you could do so yourself too if you wanted.
Something as easy as this would set a random secret.</p>

<pre><code class="hljs"><span class="hljs-keyword">use</span> <span class="hljs-function">Mojolicious::Lite</span>;

devdata/https_mojolicious.io_blog_2017_12_16_day-16-the-secret-life-of-sessions  view on Meta::CPAN

  <span class="hljs-type">$message</span> .= &#39;<span class="hljs-string">s</span>&#39; <span class="hljs-keyword">unless</span> <span class="hljs-type">$count</span> == <span class="hljs-number">1</span>;
  <span class="hljs-type">$c</span>-&gt;<span class="hljs-type">render</span>(text =&gt; <span class="hljs-type">$message</span>);
};

app-&gt;start;

</code></pre>

<p>So why isn&#39;t this recommended?
Because it would mean that each time you started the server you would get a new secret.
As with the case of changing your secret intentionally above, all existing sessions would be invalidated any time you wanted to reboot a server or restart the server process.
Additionally you could only use one server, any load balancing scenario would result in different secrets on different hosts, your users would randomly invalidate their sessions depending on which server they hit!</p>

<h2>Forward Secrecy</h2>

<p>Just as you have to change application passwords from time to time, so too you need to change your secret.
In a brute force scenario, a nefarious user could take one of their cookies and try to reverse engineer the secret that was used to generate it.</p>

<p>But wait!
You just said that changing the secret to prevent brute forcing will invalidate all of our sessions!</p>

<p>Remember when I pointed out that rather than being a single value, <code>secrets</code> was an array reference?
Well when Mojolicious generates a session cookie, it does so using the first value in the array reference.
However, when it validates session signatures, it will check them against each secret in the array.</p>

<p>So, say the time has come to rotate our secrets so we generate another</p>

<pre><code>$ &lt;/dev/urandom base64 | head -c 12
w8S4b+90CWwf
</code></pre>

<p>add that value to the configuration file</p>

<pre><code class="hljs">{



( run in 0.477 second using v1.01-cache-2.11-cpan-a5abf4f5562 )