This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/allura.git
commit 3d53e1e17b9b80be9699e3911be55c05fde9b2c4 Author: Dave Brondsema <[email protected]> AuthorDate: Wed May 13 12:14:42 2026 -0400 [#8607] check for email code mode when verifying email link --- Allura/allura/controllers/auth.py | 5 ++++- Allura/allura/tests/functional/test_auth.py | 32 ++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py index a500df93d..4bc05f5b3 100644 --- a/Allura/allura/controllers/auth.py +++ b/Allura/allura/controllers/auth.py @@ -498,7 +498,10 @@ def login_email_verify(self, token, return_to='/', **kwargs): if not c.user.is_anonymous(): redirect(self._verify_return_to(return_to)) - if not session.get('multifactor-username'): + if not session.get('multifactor-username') or session.get('mode') != 'email_code': + session.pop('multifactor-username', None) + session.pop('mode', None) + session.save() return dict(error='Your login session was disrupted.<br>Be sure to use the same browser when logging in and opening the email verification link.') user = M.User.by_username(session['multifactor-username']) diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py index e2e568370..78027e116 100644 --- a/Allura/allura/tests/functional/test_auth.py +++ b/Allura/allura/tests/functional/test_auth.py @@ -44,7 +44,7 @@ from allura.model.oauth import dummy_oauths from allura.lib import plugin from allura.lib import helpers as h -from allura.lib.multifactor import TotpService, RecoveryCodeService +from allura.lib.multifactor import TotpService, RecoveryCodeService, EmailCodeAuthenticationService def unentity(s): @@ -3218,6 +3218,36 @@ def test_login_totp_untrusted_source(self, trusted_login_source, send_system_mai assert r.location == 'http://localhost/p/foo' assert r.session.get('username') == 'test-admin' + @mock.patch.dict(config, {'auth.email_auth_code.enabled': True}) + def test_login_email_verify_requires_email_code_stage(self): + # make sure an email link can't bypass MFA + # not sure how it could happen to have a valid email link before MFA, but make sure anyway. + + self._init_totp() + + self.app.extra_environ = {'disable_auth_magic': 'True'} + user = M.User.by_username('test-admin') + token = EmailCodeAuthenticationService().generate_token(user) + + r = self.app.get('/auth/?return_to=/p/foo') + f = r.forms[0] + encoded = self.app.antispam_field_names(f) + f[encoded['username']] = 'test-admin' + f[encoded['password']] = 'foo' + r = f.submit() + + assert r.location.endswith('/auth/multifactor?return_to=%2Fp%2Ffoo'), r + r = r.follow() + assert r.session.get('multifactor-username') == 'test-admin' + assert r.session.get('mode') is None + + r = self.app.get(f'/auth/login_email_verify?token={token}&return_to=/p/foo', status=200) + + assert 'Your login session was disrupted' in r.text + assert not r.session.get('username') + assert not r.session.get('multifactor-username') + assert not r.session.get('mode') + def test_login_rate_limit(self): self._init_totp()
