Remember application state on login (issue #20)
Change-Id: Ie72bb05ee53080986749e74b87fc4f71b343c270
diff --git a/Changes b/Changes
index d1e1eb2..a632a27 100755
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-0.26 2018-02-14
+0.26 2018-03-19
- Added meta data view.
- Attach reference line to match bottom.
- Separate match views and integrate relation menu
@@ -9,6 +9,9 @@
- Generalized Poliqarp tutorials and made
example queries corpus independent.
- Improve README.
+ - Protect login for csrf attacks.
+ - Remember app state after login (issue #20).
+ - Fixed DRuKoLA annotation assistant data.
0.25 2018-01-31
- Make annotation helper configurable.
diff --git a/Makefile.PL b/Makefile.PL
index 992ef8f..1781435 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -17,6 +17,7 @@
'Mojolicious' => '7.66',
'Mojolicious::Plugin::TagHelpers::Pagination' => 0.06,
'Mojolicious::Plugin::TagHelpers::MailToChiffre' => 0.09,
+ 'Mojolicious::Plugin::ClosedRedirect' => 0.13,
'Mojolicious::Plugin::Notifications' => 1.01,
'Mojolicious::Plugin::MailException' => 0.20,
'Mojolicious::Plugin::CHI' => 0.15,
diff --git a/kalamar.dict b/kalamar.dict
index dcf75ff..b9c805d 100644
--- a/kalamar.dict
+++ b/kalamar.dict
@@ -59,7 +59,8 @@
loginFail => 'Anmeldung fehlgeschlagen',
logoutSuccess => 'Abmeldung erfolgreich',
logoutFail => 'Abmeldung fehlgeschlagen',
- csrfFail => 'Fehlerhafter CSRF Token'
+ csrfFail => 'Fehlerhafter CSRF Token',
+ openRedirectFail => 'Weiterleitungsfehler'
},
Template => {
intro => 'de/intro',
@@ -153,7 +154,8 @@
loginFail => 'Access denied',
logoutSuccess => 'Logout successful',
logoutFail => 'Logout failed',
- csrfFail => 'Bad CSRF token'
+ csrfFail => 'Bad CSRF token',
+ openRedirectFail => 'Redirect failure'
},
Template => {
intro => 'intro',
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index 43e98b6..7eec66c 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -8,11 +8,9 @@
# Minor version - may be patched from package.json
our $VERSION = '0.26';
-# TODO: Use CSRF!!!
# TODO: The FAQ-Page has a contact form for new questions
# TODO: Embed query serialization
# TODO: Embed collection statistics
-# TODO: Show further meta data per click
# TODO: Implement tab opener for matches and the tutorial
# TODO: Implement a "projects" system
@@ -130,7 +128,8 @@
'TagHelpers::MailToChiffre', # Obfuscate email addresses
'KalamarHelpers', # Specific Helpers for Kalamar
'KalamarUser', # Specific Helpers for Kalamar
- 'ClientIP' # Get client IP from X-Forwarded-For
+ 'ClientIP', # Get client IP from X-Forwarded-For
+ 'ClosedRedirect' # Redirect with OpenRedirect protection
) {
$self->plugin($_);
};
diff --git a/lib/Kalamar/Controller/User.pm b/lib/Kalamar/Controller/User.pm
index a77062d..6eb0372 100644
--- a/lib/Kalamar/Controller/User.pm
+++ b/lib/Kalamar/Controller/User.pm
@@ -10,9 +10,13 @@
$v->required('handle_or_email', 'trim');
$v->required('pwd', 'trim');
$v->csrf_protect;
+ $v->optional('fwd')->closed_redirect;
if ($v->has_error) {
- if ($v->has_error('csrf_token')) {
+ if ($v->has_error('fwd')) {
+ $c->notify(error => $c->loc('Auth_openRedirectFail'));
+ }
+ elsif ($v->has_error('csrf_token')) {
$c->notify(error => $c->loc('Auth_csrfFail'));
}
else {
@@ -36,7 +40,7 @@
$c->flash(handle_or_email => $v->param('handle_or_email'));
# Redirect to slash
- return $c->redirect_to('index');
+ return $c->relative_redirect_to($v->param('fwd') // 'index');
};
diff --git a/package.json b/package.json
index 6e75732..451ae0d 100755
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "Kalamar",
"description": "Mojolicious-based Frontend for KorAP",
"license" : "BSD-2-Clause",
- "version": "0.26.1",
+ "version": "0.26.2",
"repository" : {
"type": "git",
"url": "https://github.com/KorAP/Kalamar.git"
diff --git a/t/remote_user.t b/t/remote_user.t
index cb9a7b6..4ac8a8e 100644
--- a/t/remote_user.t
+++ b/t/remote_user.t
@@ -82,6 +82,43 @@
->content_like(qr/\"authorized\"\:null/)
;
+# Get redirect
+my $fwd = $t->get_ok('/?q=Baum&ql=poliqarp')
+ ->status_is(200)
+ ->element_exists_not('div.notify-error')
+ ->tx->res->dom->at('input[name=fwd]')->attr('value')
+ ;
+
+is($fwd, '/?q=Baum&ql=poliqarp', 'Redirect is valid');
+
+$t->post_ok('/user/login' => form => {
+ handle_or_email => 'test',
+ pwd => 'pass',
+ csrf_token => $csrf,
+ fwd => 'http://bad.example.com/test'
+})
+ ->status_is(302)
+ ->header_is('Location' => '/');
+
+$t->get_ok('/')
+ ->status_is(200)
+ ->element_exists('div.notify-error')
+ ->element_exists_not('div.notify-success')
+ ->text_is('div.notify-error', 'Redirect failure')
+ ;
+
+$t->post_ok('/user/login' => form => {
+ handle_or_email => 'test',
+ pwd => 'pass',
+ csrf_token => $csrf,
+ fwd => $fwd
+})
+ ->status_is(302)
+ ->header_is('Location' => '/?q=Baum&ql=poliqarp');
+
+
+
+
done_testing;
__END__
diff --git a/templates/layouts/main.html.ep b/templates/layouts/main.html.ep
index 78ed722..f1e993a 100644
--- a/templates/layouts/main.html.ep
+++ b/templates/layouts/main.html.ep
@@ -35,6 +35,7 @@
<legend><span><%= loc 'login' %></span></legend>
%= csrf_field
%= text_field 'handle_or_email', placeholder => loc('userormail')
+ %= hidden_field fwd => $c->url_with
<div>
%= password_field 'pwd', placeholder => loc('pwd')
<button type="submit"><span><%= loc 'go' %></span></button>