diff options
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/Catalyst/Authentication/Credential/2FA.pm | 47 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth/Profile.pm | 1 |
3 files changed, 51 insertions, 2 deletions
diff --git a/perllib/Catalyst/Authentication/Credential/2FA.pm b/perllib/Catalyst/Authentication/Credential/2FA.pm index 9f22fed11..8b6771037 100644 --- a/perllib/Catalyst/Authentication/Credential/2FA.pm +++ b/perllib/Catalyst/Authentication/Credential/2FA.pm @@ -21,11 +21,54 @@ sub authenticate { my $user_obj = $realm->find_user($userfindauthinfo, $c); if (ref($user_obj)) { - # We don't care unless user has a 2FA secret - return $user_obj unless $user_obj->get_extra_metadata('2fa_secret'); + + # We don't care unless user has a 2FA secret, or the cobrand mandates it + return $user_obj unless $user_obj->has_2fa || $c->cobrand->call_hook('must_have_2fa', $user_obj); $c->stash->{token} = $c->get_param('token'); + if (!$user_obj->has_2fa) { + $c->stash->{template} = 'auth/2fa/intro.html'; + my $action = $c->get_param('2fa_action') || ''; + + my $secret; + if ($action eq 'confirm') { + $secret = $c->get_param('secret32'); + if ($c->check_2fa($secret)) { + $user_obj->set_extra_metadata('2fa_secret' => $secret); + $user_obj->update; + if ($c->stash->{token}) { + my $token = $c->forward('/tokens/load_auth_token', [ $c->stash->{token}, '2fa' ]); + # Will contain a detach_to and report/update data + $c->stash($token->data); + } else { + $c->stash->{stage} = 'success'; + $c->stash->{detach_to} = '/auth/two_factor_setup_success'; + } + return $user_obj; + } else { + $action = 'activate'; # Incorrect code, reshow + } + } + + if ($action eq 'activate') { + my $auth = Auth::GoogleAuth->new; + $c->stash->{qr_code} = $auth->qr_code($secret, $user_obj->email, 'FixMyStreet'); + $c->stash->{secret32} = $auth->secret32; + $c->stash->{stage} = 'activate'; + } + + if ($c->stash->{tfa_data}) { + my $token = $c->model("DB::Token")->create( { + scope => '2fa', + data => $c->stash->{tfa_data}, + }); + $c->stash->{token} = $token->token; + } + + $c->detach; + } + if ($c->check_2fa($user_obj->has_2fa)) { if ($c->stash->{token}) { my $token = $c->forward('/tokens/load_auth_token', [ $c->stash->{token}, '2fa' ]); diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index 9680a5624..2aa1144a0 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -540,6 +540,11 @@ sub check_auth : Local { return; } +sub two_factor_setup_success : Private { + my ($self, $c) = @_; + # Only here to be detached to after setup success +} + __PACKAGE__->meta->make_immutable; 1; diff --git a/perllib/FixMyStreet/App/Controller/Auth/Profile.pm b/perllib/FixMyStreet/App/Controller/Auth/Profile.pm index 8512e7562..91ffac205 100644 --- a/perllib/FixMyStreet/App/Controller/Auth/Profile.pm +++ b/perllib/FixMyStreet/App/Controller/Auth/Profile.pm @@ -195,6 +195,7 @@ sub generate_token : Path('/auth/generate_token') { my $action = $c->get_param('2fa_action') || ''; $action = 'deactivate' if $c->get_param('2fa_deactivate'); $action = 'activate' if $c->get_param('2fa_activate'); + $action = 'activate' if $action eq 'deactivate' && $has_2fa && $c->cobrand->call_hook('must_have_2fa', $c->user); my $secret; if ($action eq 'deactivate') { |