diff options
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | perllib/Catalyst/Authentication/Credential/2FA.pm | 7 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Alert.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Auth/Profile.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/New.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/Update.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/User.pm | 2 | ||||
-rw-r--r-- | t/app/controller/auth.t | 1 | ||||
-rw-r--r-- | t/app/controller/auth_profile.t | 12 | ||||
-rw-r--r-- | templates/web/base/auth/generate_token.html | 2 |
11 files changed, 20 insertions, 15 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0deef93a5..49188e212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - Allow categories/Open311 questions to disable the reporting form. #2599 - Improve category edit form. #2469 - Allow editing of category name. #1398 + - Allow non-superusers to store 2FA secrets. - New features: - Categories can be listed under more than one group #2475 - OpenID Connect login support. #2523 diff --git a/perllib/Catalyst/Authentication/Credential/2FA.pm b/perllib/Catalyst/Authentication/Credential/2FA.pm index 154959ce3..22f4b4cff 100644 --- a/perllib/Catalyst/Authentication/Credential/2FA.pm +++ b/perllib/Catalyst/Authentication/Credential/2FA.pm @@ -21,8 +21,7 @@ sub authenticate { my $user_obj = $realm->find_user($userfindauthinfo, $c); if (ref($user_obj)) { - # We don't care unless user is a superuser and has a 2FA secret - return $user_obj unless $user_obj->is_superuser; + # We don't care unless user has a 2FA secret return $user_obj unless $user_obj->get_extra_metadata('2fa_secret'); $c->stash->{token} = $c->get_param('token'); @@ -91,8 +90,8 @@ with a two-factor authentication code. This authentication credential checker takes authentication information (most often a username), and only passes if a valid 2FA code is then -entered. It only works for Users that have an is_superuser flag set, -plus store the 2FA secret in a FixMyStreet::Role::Extra metadata key. +entered. It only works for Users that have a 2FA secret stored in a +FixMyStreet::Role::Extra metadata key. =head1 CONFIGURATION diff --git a/perllib/FixMyStreet/App/Controller/Alert.pm b/perllib/FixMyStreet/App/Controller/Alert.pm index 1060c080b..755602562 100644 --- a/perllib/FixMyStreet/App/Controller/Alert.pm +++ b/perllib/FixMyStreet/App/Controller/Alert.pm @@ -283,7 +283,7 @@ sub send_confirmation_email : Private { my $user = $c->stash->{alert}->user; - # Superusers using 2FA can not log in by code + # People using 2FA can not log in by code $c->detach( '/page_error_403_access_denied', [] ) if $user->has_2fa; my $token = $c->model("DB::Token")->create( diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm index e23690368..9680a5624 100644 --- a/perllib/FixMyStreet/App/Controller/Auth.pm +++ b/perllib/FixMyStreet/App/Controller/Auth.pm @@ -257,7 +257,7 @@ sub process_login : Private { $c->detach( '/page_error_403_access_denied', [] ) if FixMyStreet->config('SIGNUPS_DISABLED') && !$user->in_storage && !$data->{old_user_id}; - # Superusers using 2FA can not log in by code + # People using 2FA can not log in by code $c->detach( '/page_error_403_access_denied', [] ) if $user->has_2fa; if ($data->{old_user_id}) { diff --git a/perllib/FixMyStreet/App/Controller/Auth/Profile.pm b/perllib/FixMyStreet/App/Controller/Auth/Profile.pm index 87aff2261..107720aee 100644 --- a/perllib/FixMyStreet/App/Controller/Auth/Profile.pm +++ b/perllib/FixMyStreet/App/Controller/Auth/Profile.pm @@ -191,7 +191,7 @@ sub generate_token : Path('/auth/generate_token') { $c->stash->{token_generated} = 1; } - if ($c->get_param('toggle_2fa') && $c->user->is_superuser) { + if ($c->get_param('toggle_2fa')) { if ($has_2fa) { $c->user->unset_extra_metadata('2fa_secret'); $c->stash->{toggle_2fa_off} = 1; diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index 03623259c..cac50e34d 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -1613,7 +1613,7 @@ sub redirect_or_confirm_creation : Private { return 1; } - # Superusers using 2FA can not log in by code + # People using 2FA can not log in by code $c->detach( '/page_error_403_access_denied', [] ) if $report->user->has_2fa; # otherwise email or text a confirm token to them. diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm index 28a58d4f8..1dc337c48 100644 --- a/perllib/FixMyStreet/App/Controller/Report/Update.pm +++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm @@ -501,7 +501,7 @@ sub redirect_or_confirm_creation : Private { return 1; } - # Superusers using 2FA can not log in by code + # People using 2FA can not log in by code $c->detach( '/page_error_403_access_denied', [] ) if $update->user->has_2fa; my $data = $c->stash->{token_data}; diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index c5824af36..805ea4776 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -495,7 +495,7 @@ sub admin_user_body_permissions { sub has_2fa { my $self = shift; - return $self->is_superuser && $self->get_extra_metadata('2fa_secret'); + return $self->get_extra_metadata('2fa_secret'); } sub contributing_as { diff --git a/t/app/controller/auth.t b/t/app/controller/auth.t index ffabc75f3..fc1966b17 100644 --- a/t/app/controller/auth.t +++ b/t/app/controller/auth.t @@ -290,7 +290,6 @@ subtest "Test two-factor authentication login" => sub { my $wrong_code = $auth->code(undef, time() - 120); my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } ); - $user->is_superuser(1); $user->password('password'); $user->set_extra_metadata('2fa_secret', $auth->secret32); $user->update; diff --git a/t/app/controller/auth_profile.t b/t/app/controller/auth_profile.t index 815098caa..6cab1fb6c 100644 --- a/t/app/controller/auth_profile.t +++ b/t/app/controller/auth_profile.t @@ -359,6 +359,8 @@ subtest "Test superuser can access generate token page" => sub { $mech->get_ok('/auth/generate_token'); }; +my $body = $mech->create_body_ok(2237, 'Oxfordshire'); + subtest "Test staff user can access generate token page" => sub { my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } ); ok $user->update({ is_superuser => 0 }), 'user not superuser'; @@ -374,8 +376,6 @@ subtest "Test staff user can access generate token page" => sub { $mech->content_lacks('Security'); - my $body = $mech->create_body_ok(2237, 'Oxfordshire'); - $mech->get('/auth/generate_token'); is $mech->res->code, 403, "access denied"; @@ -428,8 +428,13 @@ subtest "Test generate token page" => sub { }; subtest "Test two-factor authentication admin" => sub { + for (0, 1) { my $user = $mech->log_in_ok($test_email); - ok $user->update({ is_superuser => 1 }), 'user set to superuser'; + if ($_) { + ok $user->update({ is_superuser => 1, from_body => undef }), 'user set to superuser'; + } else { + ok $user->update({ is_superuser => 0, from_body => $body }), 'user set to staff user'; + } $mech->get_ok('/auth/generate_token'); ok !$user->get_extra_metadata('2fa_secret'); @@ -448,4 +453,5 @@ subtest "Test two-factor authentication admin" => sub { $mech->submit_form_ok({ button => 'toggle_2fa' }, "submit 2FA deactivation"); $mech->content_contains('has been deactivated', "2FA deactivated"); + } }; diff --git a/templates/web/base/auth/generate_token.html b/templates/web/base/auth/generate_token.html index f7061be45..3c9dbf6aa 100644 --- a/templates/web/base/auth/generate_token.html +++ b/templates/web/base/auth/generate_token.html @@ -50,7 +50,7 @@ INCLUDE 'header.html', title = loc('Security'), bodyclass = 'fullwidthpage' <p> <input name="generate_token" type="submit" class="btn" value="[% existing_token ? loc('Replace token') : loc('Generate token') %]"> - [% IF c.user.is_superuser %] + [% IF c.user.is_superuser || c.user.from_body %] <input name="toggle_2fa" type="submit" class="btn" value="[% has_2fa ? loc('Deactivate two-factor authentication') : loc('Activate two-factor authentication') %]"> [% END %] </p> |