Skip to content

Commit c73d374

Browse files
committed
fix(oauth): handle popup close race
1 parent b43f7f8 commit c73d374

2 files changed

Lines changed: 14 additions & 1 deletion

File tree

app/src/lib/apps/SyncPanel.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
$: void ensureTermStateLoaded();
4747
4848
async function startGithubLogin() {
49+
gistStatus = t('panels.sync.statuses.githubAuthorizing');
4950
const result = await startGithubPkceLoginPopup();
5051
if (!result.ok) gistStatus = t(result.errorKey);
5152
}

app/src/lib/policies/github/oauthPkce.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ function attachPopupCallbackCoordinator(popup: Window, redirectUri: string) {
271271
};
272272

273273
let done = false;
274+
let popupClosedAt: number | null = null;
274275
const closePopup = () => {
275276
try {
276277
popup.close();
@@ -382,8 +383,19 @@ function attachPopupCallbackCoordinator(popup: Window, redirectUri: string) {
382383
const interval = window.setInterval(() => {
383384
if (done) return;
384385
if (popup.closed) {
385-
cleanup();
386+
// Popup may close immediately after writing callback payload (COOP can sever opener messaging).
387+
// Keep a short grace period to read the storage fallback before giving up.
388+
if (popupClosedAt === null) popupClosedAt = Date.now();
389+
const payload = readCallbackFromStorage();
390+
if (payload) {
391+
clearCallbackStorage();
392+
void onCallback(payload);
393+
return;
394+
}
395+
if (Date.now() - popupClosedAt > 2500) cleanup();
386396
return;
397+
} else {
398+
popupClosedAt = null;
387399
}
388400

389401
// If the popup navigates back to our origin, try to read its URL and complete the callback here.

0 commit comments

Comments
 (0)