Prevent csrf attacks on login
Change-Id: I9e6225f80136899e1ab90eac58d8206d2f7b1819
diff --git a/kalamar.dict b/kalamar.dict
index 8791534..dcf75ff 100644
--- a/kalamar.dict
+++ b/kalamar.dict
@@ -58,7 +58,8 @@
loginSuccess => 'Anmeldung erfolgreich',
loginFail => 'Anmeldung fehlgeschlagen',
logoutSuccess => 'Abmeldung erfolgreich',
- logoutFail => 'Abmeldung fehlgeschlagen'
+ logoutFail => 'Abmeldung fehlgeschlagen',
+ csrfFail => 'Fehlerhafter CSRF Token'
},
Template => {
intro => 'de/intro',
@@ -151,7 +152,8 @@
loginSuccess => 'Login successful',
loginFail => 'Access denied',
logoutSuccess => 'Logout successful',
- logoutFail => 'Logout failed'
+ logoutFail => 'Logout failed',
+ csrfFail => 'Bad CSRF token'
},
Template => {
intro => 'intro',
diff --git a/lib/Kalamar/Controller/User.pm b/lib/Kalamar/Controller/User.pm
index a1fab18..a77062d 100644
--- a/lib/Kalamar/Controller/User.pm
+++ b/lib/Kalamar/Controller/User.pm
@@ -9,9 +9,15 @@
my $v = $c->validation;
$v->required('handle_or_email', 'trim');
$v->required('pwd', 'trim');
+ $v->csrf_protect;
if ($v->has_error) {
- $c->notify(error => $c->loc('Auth_loginFail'));
+ if ($v->has_error('csrf_token')) {
+ $c->notify(error => $c->loc('Auth_csrfFail'));
+ }
+ else {
+ $c->notify(error => $c->loc('Auth_loginFail'));
+ };
}
# Login user
diff --git a/t/remote_user.t b/t/remote_user.t
index d90fec1..cb9a7b6 100644
--- a/t/remote_user.t
+++ b/t/remote_user.t
@@ -34,6 +34,17 @@
->status_is(302)
->header_is('Location' => '/');
+my $csrf = $t->get_ok('/')
+ ->status_is(200)
+ ->element_exists('div.notify-error')
+ ->text_is('div.notify-error', 'Bad CSRF token')
+ ->tx->res->dom->at('input[name=csrf_token]')->attr('value')
+ ;
+
+$t->post_ok('/user/login' => form => { handle_or_email => 'test', pwd => 'pass', csrf_token => $csrf })
+ ->status_is(302)
+ ->header_is('Location' => '/');
+
$t->get_ok('/')
->status_is(200)
->element_exists_not('div.notify-error')
diff --git a/templates/layouts/main.html.ep b/templates/layouts/main.html.ep
index 83b637d..78ed722 100644
--- a/templates/layouts/main.html.ep
+++ b/templates/layouts/main.html.ep
@@ -33,6 +33,7 @@
<fieldset>
%= form_for 'login', class => 'login', begin
<legend><span><%= loc 'login' %></span></legend>
+ %= csrf_field
%= text_field 'handle_or_email', placeholder => loc('userormail')
<div>
%= password_field 'pwd', placeholder => loc('pwd')