From f0911da291b55801e69132a4d6f0a312089fdc18 Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Wed, 15 Jun 2016 20:15:40 +0100 Subject: Improve auth flow taken when return key used. --- perllib/FixMyStreet/App/Controller/Auth.pm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'perllib/FixMyStreet/App/Controller/Auth.pm') diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index c5a6cf9bf..203479253 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -37,16 +37,17 @@ sub general : Path : Args(0) { # all done unless we have a form posted to us return unless $c->req->method eq 'POST'; - # decide which action to take - $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in'); - $c->detach('twitter_sign_in') if $c->get_param('twitter_sign_in'); - - my $clicked_password = $c->get_param('sign_in'); my $clicked_email = $c->get_param('email_sign_in'); + my $data_address = $c->get_param('email'); my $data_password = $c->get_param('password_sign_in'); my $data_email = $c->get_param('name') || $c->get_param('password_register'); + # decide which action to take $c->detach('email_sign_in') if $clicked_email || ($data_email && !$data_password); + if (!$data_address && !$data_password && !$data_email) { + $c->detach('facebook_sign_in') if $c->get_param('facebook_sign_in'); + $c->detach('twitter_sign_in') if $c->get_param('twitter_sign_in'); + } $c->forward( 'sign_in' ) && $c->detach( 'redirect_on_signin', [ $c->get_param('r') ] ); -- cgit v1.2.3 From 9d8ae07980bccd58e11acbc82e60b651ed20c181 Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Wed, 15 Jun 2016 20:14:51 +0100 Subject: Improve CSRF tokens and add to more forms. --- perllib/FixMyStreet/App/Controller/Auth.pm | 40 +++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'perllib/FixMyStreet/App/Controller/Auth.pm') diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index 203479253..65533b1d2 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -6,8 +6,9 @@ BEGIN { extends 'Catalyst::Controller'; } use Email::Valid; use Net::Domain::TLD; -use mySociety::AuthToken; +use Digest::HMAC_SHA1 qw(hmac_sha1); use JSON::MaybeXS; +use MIME::Base64; use Net::Facebook::Oauth2; use Net::Twitter::Lite::WithAPIv1_1; @@ -415,12 +416,13 @@ sub change_password : Local { $c->detach( 'redirect' ) unless $c->user; - # FIXME - CSRF check here - # FIXME - minimum criteria for passwords (length, contain number, etc) + $c->forward('get_csrf_token'); # If not a post then no submission return unless $c->req->method eq 'POST'; + $c->forward('check_csrf_token'); + # get the passwords my $new = $c->get_param('new_password') // ''; my $confirm = $c->get_param('confirm') // ''; @@ -444,6 +446,38 @@ sub change_password : Local { } +sub get_csrf_token : Private { + my ( $self, $c ) = @_; + + my $time = $c->stash->{csrf_time} || time(); + my $hash = hmac_sha1("$time-" . ($c->sessionid || ""), $c->model('DB::Secret')->get); + $hash = encode_base64($hash, ""); + $hash =~ s/=$//; + my $token = "$time-$hash"; + $c->stash->{csrf_token} = $token unless $c->stash->{csrf_time}; + return $token; +} + +sub check_csrf_token : Private { + my ( $self, $c ) = @_; + + my $token = $c->get_param('token') || ""; + $token =~ s/ /+/g; + my ($time) = $token =~ /^(\d+)-[0-9a-zA-Z+\/]+$/; + $c->stash->{csrf_time} = $time; + $c->detach('no_csrf_token') + unless $time + && $time > time() - 3600 + && $token eq $c->forward('get_csrf_token'); + delete $c->stash->{csrf_time}; +} + +sub no_csrf_token : Private { + my ($self, $c) = @_; + $c->stash->{message} = _('Unknown error'); + $c->stash->{template} = 'errors/generic.html'; +} + =head2 sign_out Log the user out. Tell them we've done so. -- cgit v1.2.3 From f74c7910b72f41f4a72d8b6b1a683fcf9fbb244e Mon Sep 17 00:00:00 2001 From: Matthew Somerville Date: Tue, 5 Jul 2016 13:09:18 +0100 Subject: Fix CSRF issue with new login during process. If you had no session cookie, started reporting a problem, logged in through that process, you would then get a CSRF error as the token had been created before the session was. --- perllib/FixMyStreet/App/Controller/Auth.pm | 3 +++ 1 file changed, 3 insertions(+) (limited to 'perllib/FixMyStreet/App/Controller/Auth.pm') diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index 65533b1d2..be95040e1 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -85,6 +85,9 @@ sub sign_in : Private { $c->set_session_cookie_expire(0) unless $remember_me; + # Regenerate CSRF token as session ID changed + $c->forward('get_csrf_token'); + return 1; } -- cgit v1.2.3