From 0850f6a13b3780be908e8bbe7b755bae5744585e Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sun, 12 Jul 2026 04:52:31 +0200 Subject: [PATCH] fix(auth): decrypt the access-token fallback before revoking on account deletion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit purge_user's revoke used `decrypt(refresh) or tok.access_token`, but access_token is stored ENCRYPTED — so a token row without a refresh token would send ciphertext to Google's revoke endpoint and silently fail. Decrypt it. (Pre-existing; surfaced by the review of the OAuth-scope fix.) --- backend/app/auth.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/app/auth.py b/backend/app/auth.py index dcf0d88..5f814d6 100644 --- a/backend/app/auth.py +++ b/backend/app/auth.py @@ -440,7 +440,9 @@ def purge_user(db: Session, user: User, background: BackgroundTasks) -> None: email = user.email.lower() user_id = user.id tok = user.token - google_token = (decrypt(tok.refresh_token_enc) or tok.access_token) if tok else None + # Both are stored encrypted — decrypt for the revoke call (the access-token fallback was passing + # ciphertext, so a token row with no refresh token silently failed to revoke). + google_token = (decrypt(tok.refresh_token_enc) or decrypt(tok.access_token)) if tok else None # Raw delete so Postgres applies ON DELETE CASCADE / SET NULL on every dependent table. db.execute(delete(User).where(User.id == user_id)) db.execute(delete(Invite).where(Invite.email == email))