Disable caching in auth routes

Change-Id: I0518056c017dfa4ae7feca730558d0dcb821475a
diff --git a/Changes b/Changes
index 706386a..2e16e4b 100755
--- a/Changes
+++ b/Changes
@@ -22,6 +22,7 @@
         - Fixed bug where missing documentation pages raise
           exceptions in Mojo >= 9.0.
         - Support revocation of tokens.
+        - Disable caching in auth routes.
 
         WARNING: Upgrading to Mojolicious 9.19 will
           invalidate all sessions. This is a security update.
diff --git a/lib/Kalamar/Plugin/Auth.pm b/lib/Kalamar/Plugin/Auth.pm
index dba5181..29dbe36 100644
--- a/lib/Kalamar/Plugin/Auth.pm
+++ b/lib/Kalamar/Plugin/Auth.pm
@@ -732,6 +732,8 @@
         cb => sub {
           my $c = shift;
 
+          _set_no_cache($c->res->headers);
+
           unless ($c->auth->token) {
             return $c->render(
               content => 'Unauthorized',
@@ -762,6 +764,9 @@
       $r->post('/settings/oauth/register')->to(
         cb => sub {
           my $c = shift;
+
+          _set_no_cache($c->res->headers);
+
           my $v = $c->validation;
 
           unless ($c->auth->token) {
@@ -849,7 +854,9 @@
       # Unregister client page
       $r->get('/settings/oauth/:client_id/unregister')->to(
         cb => sub {
-          shift->render(template => 'auth/unregister');
+          my $c = shift;
+          _set_no_cache($c->res->headers);
+          $c->render(template => 'auth/unregister');
         }
       )->name('oauth-unregister');
 
@@ -858,6 +865,7 @@
       $r->post('/settings/oauth/:client_id/unregister')->to(
         cb => sub {
           my $c = shift;
+          _set_no_cache($c->res->headers);
 
           my $v = $c->validation;
 
@@ -930,6 +938,8 @@
         cb => sub {
           my $c = shift;
 
+          _set_no_cache($c->res->headers);
+
           $c->render_later;
 
           $c->auth->client_list_p->then(
@@ -978,7 +988,9 @@
     # Ask if new token should be issued
     $r->get('/settings/oauth/:client_id/token')->to(
       cb => sub {
-        shift->render(template => 'auth/issue-token');
+        my $c = shift;
+        _set_no_cache($c->res->headers);
+        $c->render(template => 'auth/issue-token');
       }
     )->name('oauth-issue-token');
 
@@ -995,6 +1007,7 @@
     $r->post('/settings/oauth/:client_id/token')->to(
       cb => sub {
         my $c = shift;
+        _set_no_cache($c->res->headers);
 
         my $v = $c->validation;
 
@@ -1412,6 +1425,15 @@
 };
 
 
+# Set 'no caching' headers
+sub _set_no_cache {
+  my $h = shift;
+  $h->cache_control('max-age=0, no-cache, no-store, must-revalidate');
+  $h->expires('Thu, 01 Jan 1970 00:00:00 GMT');
+  $h->header('Pragma','no-cache');
+};
+
+
 1;
 
 
diff --git a/t/plugin/auth-oauth.t b/t/plugin/auth-oauth.t
index a531bc5..1159964 100644
--- a/t/plugin/auth-oauth.t
+++ b/t/plugin/auth-oauth.t
@@ -436,12 +436,11 @@
   ->attr_is('form.oauth-register','action', '/settings/oauth/register')
   ->element_exists('ul.client-list')
   ->element_exists_not('ul.client-list > li')
-#  ->text_is('ul.client-list > li > span.client-name', 'R statistical computing tool ')
-#  ->text_is('ul.client-list > li > span.client-desc', 'R is a free software environment for statistical computing and graphics.')
-#  ->text_is('ul.client-list > li > span.client-url a', 'https://www.r-project.org/')
-#  ->text_is('ul.client-list > li a.client-unregister', 'Unregister')
-#  ->attr_is('ul.client-list > li a.client-unregister', 'href', '/settings/oauth/unregister/9aHsGW6QflV13ixNpez?name=R+statistical+computing+tool')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
+
 $csrf = $t->post_ok('/settings/oauth/register' => form => {
   name => 'MyApp',
   type => 'PUBLIC',
@@ -464,6 +463,9 @@
   ->text_is('label[for=client_id]', 'ID of the client application')
   ->element_exists('input[name=client_id][readonly][value]')
   ->element_exists('input[name=client_secret][readonly][value]')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $t->get_ok('/settings/oauth')
@@ -472,6 +474,9 @@
   ->text_is('ul.client-list > li > span.client-name a', 'MyApp')
   ->text_is('ul.client-list > li > span.client-desc', 'This is my application')
   ->text_is('ul.client-list > li > span.client-url a', '')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
@@ -485,6 +490,9 @@
 $csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister?name=MyApp')
   ->content_like(qr!Do you really want to unregister \<span class="client-name"\>MyApp\<\/span\>?!)
   ->attr_is('.form-table input[name=client-name]', 'value', 'MyApp')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ->tx->res->dom->at('input[name="csrf_token"]')
   ->attr('value')
   ;
@@ -502,6 +510,9 @@
   ->attr_is('.oauth-register','action', '/settings/oauth/register')
   ->element_exists('ul.client-list > li')
   ->text_is('div.notify', 'Unknown client with xxxx==.')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $t->post_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/unregister' => form => {
@@ -517,6 +528,9 @@
   ->attr_is('.oauth-register','action', '/settings/oauth/register')
   ->element_exists_not('ul.client-list > li')
   ->text_is('div.notify-success', 'Successfully deleted MyApp')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $t->post_ok('/settings/oauth/register' => form => {
@@ -530,6 +544,9 @@
   ->text_is('label[for=client_id]', 'ID of the client application')
   ->element_exists('input[name=client_id][readonly][value]')
   ->element_exists_not('input[name=client_secret][readonly][value]')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
@@ -537,6 +554,9 @@
   ->text_is('.client-desc', 'This is my application')
   ->text_is('.client-issue-token', 'IssueToken')
   ->attr_is('.client-issue-token', 'href', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?name=MyApp2')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token?name=MyApp2')
@@ -544,6 +564,9 @@
   ->attr_is('#issue-token','action', '/settings/oauth/fCBbQkA2NDA3MzM1Yw==/token')
   ->attr_is('input[name=client-id]', 'value', 'fCBbQkA2NDA3MzM1Yw==')
   ->attr_is('input[name=name]', 'value', 'MyApp2')
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ->tx->res->dom->at('input[name="csrf_token"]')
   ->attr('value')
   ;
@@ -560,6 +583,10 @@
 $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')
   ->status_is(200)
   ->text_is('div.notify-success', 'New access token created')
+  ->status_is(200)
+  ->header_is('Cache-Control','max-age=0, no-cache, no-store, must-revalidate')
+  ->header_is('Expires','Thu, 01 Jan 1970 00:00:00 GMT')
+  ->header_is('Pragma','no-cache')
   ;
 
 $csrf = $t->get_ok('/settings/oauth/fCBbQkA2NDA3MzM1Yw==')