From ce9643cb840199ee7176bade990b96f9fb706e8d Mon Sep 17 00:00:00 2001 From: Oscar White <32415764+Finchow@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:52:08 +0100 Subject: [PATCH] fix(auth): drop popup.closed check in Plex pin poll (#2941) --- src/utils/plex.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/utils/plex.ts b/src/utils/plex.ts index 0c6a3941f..1b2a0a8f5 100644 --- a/src/utils/plex.ts +++ b/src/utils/plex.ts @@ -122,6 +122,10 @@ class PlexOAuth { } private async pinPoll(): Promise { + // popup.closed is unreliable under COOP same-origin-allow-popups once the + // popup navigates to app.plex.tv; bound polling by expiresAt with a 15m + // hard fallback. + const deadline = Date.now() + 15 * 60 * 1000; const executePoll = async ( resolve: (authToken: string) => void, reject: (e: Error) => void @@ -140,10 +144,16 @@ class PlexOAuth { this.authToken = response.data.authToken as string; this.closePopup(); resolve(this.authToken); - } else if (this.popup && !this.popup.closed) { - setTimeout(executePoll, 1000, resolve, reject); } else { - reject(new Error('Popup closed without completing login')); + const expiresAt = response.data?.expiresAt + ? Date.parse(response.data.expiresAt) + : deadline; + if (Date.now() >= Math.min(expiresAt, deadline)) { + this.closePopup(); + reject(new Error('Plex PIN expired before login completed.')); + return; + } + setTimeout(executePoll, 1000, resolve, reject); } } catch (e) { this.closePopup();