OTP security hardened

This commit is contained in:
2026-08-26 18:24:02 +02:00
parent c3c3c8e1a6
commit 580c2a4257
13 changed files with 227 additions and 13 deletions
+26
View File
@@ -239,6 +239,32 @@ def test_admin_can_add_list_and_remove_users():
assert client.put('/api/admin/users/user-1', headers=headers, json={'is_admin': False}).status_code == 400
def test_admin_can_reset_another_users_otp():
admin_headers = login_headers()
user_login = client.post('/api/auth/login', json={
'email': 'bob@example.com',
'password': 'secret123',
}).json()
user_headers = {'Authorization': f"Bearer {user_login['access_token']}"}
setup = client.post('/api/user/otp/setup', headers=user_headers)
assert setup.status_code == 200
secret = setup.json()['secret']
recovery_code = setup.json()['recovery_codes'][0]
assert client.post('/api/user/otp', headers=user_headers, json={
'action': 'enable', 'code': current_code(secret),
}).status_code == 200
assert client.post('/api/admin/users/user-2/otp/reset', headers=admin_headers).json() == {
'status': 'otp_reset', 'enabled': False, 'user_id': 'user-2',
}
assert client.get('/api/user/otp', headers=user_headers).json() == {'enabled': False}
assert client.post('/api/user/otp/recover', headers=user_headers, json={
'current_password': 'secret123', 'recovery_code': recovery_code,
}).status_code == 400
assert client.post('/api/admin/users/user-2/otp/reset', headers=login_headers('bob')).status_code == 403
assert client.post('/api/admin/users/missing-user/otp/reset', headers=admin_headers).status_code == 404
def test_new_user_must_verify_email_before_login():
headers = login_headers()
username = f'unverified-{uuid4().hex}'