From 974d92ab4d9632a875120135e49c4897128e44b4 Mon Sep 17 00:00:00 2001 From: Keith Smith Date: Sun, 16 Aug 2026 20:04:11 -0600 Subject: [PATCH] Unsubscribe from push notifications on logout logout() cleared the session but never called unsubscribeFromPush(), so a browser's push subscription (and its server-side row) outlived the session indefinitely -- the logged-out account kept silently receiving pushes for as long as that browser stayed open. Runs before the session cookie is cleared since the unsubscribe call is authenticated, and is best-effort so a failure there can't block logout itself. Co-Authored-By: Claude Sonnet 5 --- frontend/src/context/AuthContext.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index c53166a..f149a8f 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -2,6 +2,7 @@ import { createContext, useContext, useEffect, useState, type ReactNode } from ' import * as authApi from '../api/auth' import { ApiError, NetworkError } from '../api/client' import { clearLastUser, loadLastUser, saveLastUser } from '../lib/lastUser' +import { unsubscribeFromPush } from '../lib/push' import type { User } from '../types' interface AuthContextValue { @@ -67,6 +68,17 @@ export function AuthProvider({ children }: { children: ReactNode }) { } async function logout() { + // Best-effort, and must run before the session cookie is cleared below + // -- the unsubscribe call is authenticated. Otherwise this browser's + // push subscription (both the server-side row and the registration + // itself) outlives the session, so the account being logged out of + // keeps silently receiving pushes for as long as this browser stays + // installed/open, with no way for the user to tell why. + try { + await unsubscribeFromPush() + } catch { + // Not fatal -- logging out must still proceed even if this failed. + } await authApi.logout() setUser(null) clearLastUser()