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')