fix(auth): a Google sign-in that makes an account admin drops a password nobody proved
The never-activated rule left one order of events open: on an instance without SMTP, a stranger who registered an ADMIN_EMAILS address (or a sibling spelling) and was then activated by another admin kept their password and live session, and the owner's first Google sign-in raised that row to admin, the stranger's cookie with it. Activation vouches for access, not for who chose the password, and without SMTP nothing else ever proved the mailbox. When ADMIN_EMAILS promotes an adopted account that holds a password on an instance without SMTP, the password goes and the session epoch is bumped. With SMTP the verified flag is a proven mailbox, and an account the sign-in does not promote keeps its password, so the "your password was cleared" detour stays off the default path. Tests: the activated squat (red without the rule; the squatter's session is signed out) and the SMTP case that keeps the password.
This commit is contained in:
@@ -81,13 +81,54 @@ def test_a_no_smtp_squat_of_an_admin_address_loses_its_password(client, db, goog
|
||||
)
|
||||
|
||||
|
||||
def test_an_activated_squat_loses_its_password_when_the_sign_in_makes_it_admin(
|
||||
client, db, google, make_user, monkeypatch
|
||||
):
|
||||
# The same squat after an admin clicked Activate on it: activation vouches for access, not for
|
||||
# who chose the password, and without SMTP nothing else ever proved the mailbox. ADMIN_EMAILS
|
||||
# must not raise the squatter's live session to admin.
|
||||
monkeypatch.setattr(auth_routes.email_mod, "email_enabled", lambda: False)
|
||||
monkeypatch.setattr(settings, "admin_emails", "bob@gmail.com")
|
||||
squat = make_user(email="b.ob@gmail.com", password="the squatter's own", is_active=True)
|
||||
squatter = client.__class__(client.app)
|
||||
assert (
|
||||
squatter.post(
|
||||
"/auth/password-login",
|
||||
json={"email": "b.ob@gmail.com", "password": "the squatter's own"},
|
||||
).status_code
|
||||
== 200
|
||||
)
|
||||
|
||||
_sign_in(client, google, sub="sub-bob", email="bob@gmail.com")
|
||||
|
||||
db.refresh(squat)
|
||||
assert squat.role == "admin"
|
||||
assert squat.password_hash is None and squat.password_revoked_at is not None
|
||||
assert squatter.get("/api/me").json() == {"authenticated": False}
|
||||
|
||||
|
||||
def test_with_smtp_a_verified_account_made_admin_keeps_its_password(
|
||||
client, db, google, make_user, monkeypatch
|
||||
):
|
||||
# With SMTP the verified flag is a proven mailbox, so the promotion takes nothing away.
|
||||
monkeypatch.setattr(auth_routes.email_mod, "email_enabled", lambda: True)
|
||||
monkeypatch.setattr(settings, "admin_emails", "own@example.com")
|
||||
user = make_user(email="own@example.com", password=_PW, is_active=True)
|
||||
|
||||
_sign_in(client, google, sub="sub-own", email="own@example.com")
|
||||
|
||||
db.refresh(user)
|
||||
assert user.role == "admin" and user.password_hash is not None
|
||||
|
||||
|
||||
def test_adopting_an_account_already_let_in_keeps_its_password(
|
||||
client, db, google, make_user, monkeypatch
|
||||
):
|
||||
# The revoke is for passwords nobody vouched for; an active, verified account's own password
|
||||
# is not one of them.
|
||||
# The revoke is for passwords nobody vouched for; an active, verified account that this sign-in
|
||||
# does not make admin keeps its own.
|
||||
monkeypatch.setattr(auth_routes.email_mod, "email_enabled", lambda: False)
|
||||
user = make_user(email="kept@example.com", password=_PW, is_active=True)
|
||||
monkeypatch.setattr(settings, "admin_emails", "kept@example.com")
|
||||
monkeypatch.setattr(settings, "allowed_emails", "kept@example.com")
|
||||
|
||||
_sign_in(client, google, sub="sub-kept", email="kept@example.com")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user