+13
-37
frontend/utils/pwa.ts
+13
-37
frontend/utils/pwa.ts
···
148
148
pollForResult();
149
149
console.log("[PWA OAuth] First poll executed");
150
150
151
-
// Check if popup was closed
152
-
let checkCount = 0;
153
-
const checkClosed = setInterval(() => {
154
-
checkCount++;
155
-
const isClosed = popup.closed;
156
-
// Log every check to debug
157
-
console.log(
158
-
"[PWA OAuth] Check #" + checkCount + ", popup.closed:",
159
-
isClosed,
160
-
);
151
+
// Don't rely on popup.closed - it returns true when popup navigates cross-origin
152
+
// Instead, use a timeout. OAuth should complete within 5 minutes max.
153
+
const OAUTH_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
154
+
const startTime = Date.now();
161
155
162
-
if (isClosed) {
163
-
console.log("[PWA OAuth] Popup detected as closed, waiting 300ms...");
164
-
// Give a brief moment for any final localStorage write
165
-
setTimeout(() => {
166
-
const result = localStorage.getItem("pwa-oauth-result");
167
-
console.log(
168
-
"[PWA OAuth] Final localStorage check:",
169
-
result ? "FOUND" : "empty",
170
-
);
171
-
if (result) {
172
-
try {
173
-
const data = JSON.parse(result);
174
-
if (data?.type === "oauth-callback" && data.success) {
175
-
handleSuccess({ did: data.did, handle: data.handle });
176
-
return;
177
-
}
178
-
} catch {
179
-
// Ignore parse errors
180
-
}
181
-
}
182
-
console.log("[PWA OAuth] No result found, rejecting with cancelled");
183
-
cleanup();
184
-
reject(new Error("Login cancelled"));
185
-
}, 300);
186
-
clearInterval(checkClosed); // Stop checking for closed
156
+
const checkTimeout = setInterval(() => {
157
+
const elapsed = Date.now() - startTime;
158
+
if (elapsed > OAUTH_TIMEOUT_MS) {
159
+
console.log("[PWA OAuth] Timeout reached after 5 minutes");
160
+
cleanup();
161
+
reject(new Error("Login timed out"));
162
+
clearInterval(checkTimeout);
187
163
}
188
-
}, 500);
164
+
}, 10000); // Check every 10 seconds
189
165
190
166
function cleanup() {
191
167
console.log("[PWA OAuth] Cleanup called");
192
168
pollingStopped = true;
193
169
globalThis.removeEventListener("message", handleMessage);
194
170
globalThis.removeEventListener("storage", handleStorage);
195
-
clearInterval(checkClosed);
171
+
clearInterval(checkTimeout);
196
172
}
197
173
198
174
globalThis.addEventListener("message", handleMessage);