Implement token refresh mechanism
Change-Id: Id58e14f663ebdd86f3f2206d4bfb9ad5d87a35fa
diff --git a/t/plugin/auth-oauth.t b/t/plugin/auth-oauth.t
index 17c3cda..4ce999a 100644
--- a/t/plugin/auth-oauth.t
+++ b/t/plugin/auth-oauth.t
@@ -1,6 +1,6 @@
use Mojo::Base -strict;
use Test::More;
-use Test::Mojo;
+use Test::Mojo::WithRoles 'Session';
use Mojo::File qw/path/;
use Data::Dumper;
@@ -11,7 +11,7 @@
my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
-my $t = Test::Mojo->new('Kalamar' => {
+my $t = Test::Mojo::WithRoles->new('Kalamar' => {
Kalamar => {
plugins => ['Auth']
},
@@ -32,7 +32,70 @@
}
);
# Configure fake backend
-$fake_backend->pattern->defaults->{app}->log($t->app->log);
+my $fake_backend_app = $fake_backend->pattern->defaults->{app};
+
+# Set general app logger for simplicity
+$fake_backend_app->log($t->app->log);
+
+my $access_token = $fake_backend_app->get_token('access_token');
+my $refresh_token = $fake_backend_app->get_token('refresh_token');
+my $access_token_2 = $fake_backend_app->get_token('access_token_2');
+my $refresh_token_2 = $fake_backend_app->get_token('refresh_token_2');
+
+# Some routes to modify the session
+# This expires the session
+$t->app->routes->get('/x/expire')->to(
+ cb => sub {
+ my $c = shift;
+ $c->session(auth_exp => 0);
+ return $c->render(text => 'okay')
+ }
+);
+
+# This expires the session and removes the refresh token
+$t->app->routes->get('/x/expire-no-refresh')->to(
+ cb => sub {
+ my $c = shift;
+ $c->session(auth_exp => 0);
+ delete $c->session->{auth_r};
+ return $c->render(text => 'okay')
+ }
+);
+
+# This sets an invalid token
+$t->app->routes->get('/x/invalid')->to(
+ cb => sub {
+ my $c = shift;
+ $c->session(auth_exp => time + 1000);
+ $c->session(auth_r => $refresh_token_2);
+ $c->session(auth => 'Bearer inv4lid');
+ return $c->render(text => 'okay')
+ }
+);
+
+
+# This sets an invalid token
+$t->app->routes->get('/x/invalid-no-refresh')->to(
+ cb => sub {
+ my $c = shift;
+ $c->session(auth_exp => time + 1000);
+ delete $c->session->{auth_r};
+ $c->session(auth => 'Bearer inv4lid');
+ return $c->render(text => 'okay')
+ }
+);
+
+# This sets an invalid refresh token
+$t->app->routes->get('/x/expired-with-wrong-refresh')->to(
+ cb => sub {
+ my $c = shift;
+ $c->session(auth_exp => 0);
+ $c->session(auth => 'Bearer inv4lid');
+ $c->session(auth_r => 'inv4lid');
+ return $c->render(text => 'okay')
+ }
+);
+
$t->get_ok('/realapi/v1.0')
->status_is(200)
@@ -203,91 +266,113 @@
->element_exists_not('div.notify-error')
->element_exists('div.notify-success')
->text_is('div.notify-success', 'Login successful')
+ ->session_has('/auth')
+ ->session_is('/auth', 'Bearer ' . $access_token)
+ ->session_is('/auth_r', $refresh_token)
+ ->header_isnt('X-Kalamar-Cache', 'true')
;
-$t->app->routes->get(
- '/user/refresh' => sub {
- my $c = shift;
-
- my $old_auth = $c->auth->token;
- my $refresh = $c->chi('user')->get("refr_$old_auth");
-
- $c->auth->refresh_token($refresh)->then(
- sub {
- my $new_auth = $c->auth->token;
- $c->notify(success => $new_auth . ' vs. ' . $old_auth);
- }
- )->catch(
- sub {
-
- # Notify the user on login failure
- unless (@_) {
- $c->notify(error => $c->loc('Auth_refreshFail'));
- }
-
- # There are known errors
- foreach (@_) {
- if (ref $_ eq 'HASH') {
- my $err = ($_->{code} ? $_->{code} . ': ' : '') .
- $_->{message};
- $c->notify(error => $err);
- }
- else {
- $c->notify(error => $_);
- }
- };
- }
- )->finally(
- sub {
- return $c->redirect_to('index');
- }
- )->wait;
- }
-);
-
-$t->get_ok('/user/refresh')
- ->status_is(302)
- ->header_is('Location' => '/');
-
-$t->get_ok('/')
+# Expire the session
+# (makes the token be marked as expired - though it isn't serverside)
+$t->get_ok('/x/expire')
->status_is(200)
- ->element_exists_not('div.notify-error')
- ->element_exists('div.notify-success')
- ->text_like('div.notify-success', qr!Bearer abcde vs\. Bearer .{6,}!)
+ ->content_is('okay')
+ ;
+
+## It may be a problem, but the cache is still valid
+$t->get_ok('/?q=Baum')
+ ->status_is(200)
+ ->text_like('h1 span', qr/KorAP: Find .Baum./i)
+ ->text_like('#total-results', qr/\d+$/)
+ ->content_like(qr/\"authorized\"\:\"yes\"/)
+ ->header_is('X-Kalamar-Cache', 'true')
+ ;
+
+# Query without partial cache (unfortunately) (but no total results)
+$t->get_ok('/?q=baum&cutoff=true')
+ ->status_is(200)
+ ->session_is('/auth', 'Bearer ' . $access_token_2)
+ ->session_is('/auth_r', $refresh_token_2)
+ ->text_is('#error','')
+ ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
+ ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
+ ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
+ ->content_like(qr/\"authorized\"\:\"yes\"/)
+ ->header_isnt('X-Kalamar-Cache', 'true')
+ ->content_like(qr!\"cutOff":true!)
+ ->element_exists_not('#total-results')
+ ;
+
+# Expire the session and remove the refresh option
+$t->get_ok('/x/expire-no-refresh')
+ ->status_is(200)
+ ->content_is('okay')
+ ;
+
+$t->app->defaults(no_cache => 1);
+
+
+$t->get_ok('/x/invalid-no-refresh')
+ ->status_is(200)
+ ->content_is('okay')
+ ;
+
+# Query without cache
+# The token is invalid and can't be refreshed!
+$t->get_ok('/?q=baum&cutoff=true')
+ ->status_is(200)
+ ->session_hasnt('/auth')
+ ->session_hasnt('/auth_r')
+ ->text_is('#error','')
+ ->text_is('div.notify-error','Access token invalid')
+ ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
+ ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
+ ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
+ ->content_unlike(qr/\"authorized\"\:\"yes\"/)
+ ->header_isnt('X-Kalamar-Cache', 'true')
+ ->element_exists('p.no-results')
+ ;
+
+$t->get_ok('/x/invalid')
+ ->status_is(200)
+ ->content_is('okay')
+ ;
+
+# Query without cache
+# The token is invalid and can't be refreshed!
+$t->get_ok('/?q=baum&cutoff=true')
+ ->status_is(200)
+ ->session_is('/auth', 'Bearer ' . $access_token_2)
+ ->session_is('/auth_r', $refresh_token_2)
+ ->text_is('#error','')
+ ->element_exists_not('div.notify-error','Access token invalid')
+ ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
+ ->element_exists('meta[name="DC.title"][content="KorAP: Find »baum« with Poliqarp"]')
+ ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
+ ->content_like(qr/\"authorized\"\:\"yes\"/)
+ ->header_isnt('X-Kalamar-Cache', 'true')
+ ->element_exists_not('p.no-results')
;
-# Test before_korap_request_hook
-my $app = $t->app;
-my $c = $app->build_controller;
-my $tx = $app->build_tx('GET', 'https://korap.ids-mannheim.de/');
+$t->get_ok('/x/expired-with-wrong-refresh')
+ ->status_is(200)
+ ->content_is('okay')
+ ;
-# Emit Hook to alter request
-$app->plugins->emit_hook(
- before_korap_request => ($c, $tx)
-);
-ok(!$tx->req->headers->authorization, 'No authorization');
+# The token is invalid and can't be refreshed!
+$t->get_ok('/?q=baum&cutoff=true')
+ ->status_is(200)
+ ->session_hasnt('/auth')
+ ->session_hasnt('/auth_r')
+ ->text_is('#error','')
+ ->text_is('div.notify-error','Refresh token is expired')
+ ->text_is('title', 'KorAP: Find »baum« with Poliqarp')
+ ->content_unlike(qr/\"authorized\"\:\"yes\"/)
+ ->element_exists('p.no-results')
+ ;
-# Set token
-$c->auth->token('abcd');
-
-# Emit Hook to alter request
-$app->plugins->emit_hook(
- before_korap_request => ($c, $tx)
-);
-
-is($tx->req->headers->authorization, 'abcd', 'authorization');
-
-# Override authorization in header
-$tx->req->headers->authorization('xyz');
-
-# Emit Hook to alter request
-$app->plugins->emit_hook(
- before_korap_request => ($c, $tx)
-);
-
-is($tx->req->headers->authorization, 'xyz', 'authorization');
done_testing;
__END__