Skip to content

Commit 27410ec

Browse files
committed
Add an option to skip two factor authentication on trusted devices.
A checkbox is added to the two factor verification page. If that is checked, then a signed cookie (separate from the session cookie) is set. If that cookie is set, then two factor verification is skipped for sign in attempts.
1 parent 660d24b commit 27410ec

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

lib/WeBWorK/Authen.pm

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,31 @@ sub verify {
156156

157157
$self->{was_verified} = $self->do_verify;
158158

159+
my $remember_2fa = $c->signed_cookie('WeBWorK.2FA.' . $c->ce->{courseName});
160+
161+
if ($self->{was_verified} && $remember_2fa && !$c->db->getPassword($self->{user_id})->otp_secret) {
162+
# If there is not a otp secret saved in the database, and there is a cookie saved to skip two factor
163+
# authentication, then delete it. The user needs to set up two factor authentication again.
164+
$c->signed_cookie(
165+
'WeBWorK.2FA.' . $c->ce->{courseName} => 1,
166+
{
167+
max_age => 0,
168+
expires => 1,
169+
path => $c->ce->{webworkURLRoot},
170+
samesite => $c->ce->{CookieSameSite},
171+
secure => $c->ce->{CookieSecure},
172+
httponly => 1
173+
}
174+
);
175+
$remember_2fa = 0;
176+
}
177+
159178
if ($self->{was_verified}
160179
&& $self->{login_type} eq 'normal'
161-
&& $c->ce->two_factor_authentication_enabled
162180
&& !$self->{external_auth}
163-
&& ($self->{initial_login} || $self->session->{two_factor_verification_needed}))
181+
&& $c->ce->two_factor_authentication_enabled
182+
&& ($self->{initial_login} || $self->session->{two_factor_verification_needed})
183+
&& !$remember_2fa)
164184
{
165185
$self->{was_verified} = 0;
166186
$self->session(two_factor_verification_needed => 1);
@@ -445,6 +465,20 @@ sub verify_normal_user {
445465
{
446466
delete $self->session->{two_factor_verification_needed};
447467

468+
# Store a cookie that signifies this devices skips two factor
469+
# authentication if the skip_2fa checkbox was checked.
470+
$c->signed_cookie(
471+
'WeBWorK.2FA.' . $c->ce->{courseName} => 1,
472+
{
473+
max_age => 3600 * 24 * 365, # This cookie is valid for one year.
474+
expires => time + 3600 * 24 * 365,
475+
path => $c->ce->{webworkURLRoot},
476+
samesite => $c->ce->{CookieSameSite},
477+
secure => $c->ce->{CookieSecure},
478+
httponly => 1
479+
}
480+
) if $c->param('skip_2fa');
481+
448482
# This is the case of initial setup. Save the secret from the session to the database.
449483
if ($self->session->{otp_secret}) {
450484
$password->otp_secret($self->session->{otp_secret});

templates/ContentGenerator/TwoFactorAuthentication.html.ep

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,21 @@
3636
<%= form_for current_route, method => 'POST', begin =%>
3737
<%= $hidden_fields =%>
3838
%
39-
<div class="col-xl-5 col-lg-6 col-md-7 col-sm-8 my-3">
39+
<div class="col-xl-9 col-lg-10 col-md-11 my-3">
4040
<div class="form-floating mb-2">
4141
<%= text_field otp_code => '', id => 'otp_code', class => 'form-control', placeholder => '',
4242
autocomplete => 'off', autocapitalize => 'none', spellcheck => 'false' =%>
4343
<%= label_for otp_code => maketext('One-Time Code') =%>
4444
</div>
45+
<div class="form-check mb-2">
46+
<%= check_box(skip_2fa => 1, id => 'skip_2fa', class => 'form-check-input') =%>
47+
<%= label_for skip_2fa => maketext('Skip two factor verification on this device.') =%>
48+
</div>
49+
<div class="alert alert-warning mb-2">
50+
<%= maketext('If you check the box above, then two factor verification will be skipped from now on when '
51+
. 'signing in with this browser. This feature is not safe for public workstations, untrusted machines, '
52+
. 'and machines over which you do not have direct control.') =%>
53+
</div>
4554
% if ($authen_error) {
4655
<div class="alert alert-danger" tabindex="0"><%= $authen_error =%></div>
4756
% }

0 commit comments

Comments
 (0)