Clicking Login with Plex using Brave on my iPad does nothing. No popup opens, no error is shown to the user, and the polling loop never starts. The same Organizr instance works correctly in desktop browsers (Brave, Chrome, Firefox, Safari on macOS).
Environment
- Organizr image:
organizr/organizr:latest
- Reverse proxy: SWAG (nginx) with HTTPS
- Confirmed failing on: iPadOS Brave, incognito mode, Brave Shields disabled, "Block cross-site cookies" off, popup blocker off
- Also fails on iPadOS Safari (same WebKit engine)
- Works on: desktop Brave, desktop Chrome
Root cause
Three iOS WebKit quirks combine to kill the click handler before the PIN fetch ever runs. All three are in functions.js:
1. window.open("") is rejected on iOS
In PlexOAuth() (around line 14707):
plex_oauth_window = PopupCenter("", "Plex-OAuth", 600, 700);
iOS WebKit silently refuses window.open() with an empty-string URL. Using "about:blank" is accepted.
2. Features string with spaces is rejected
In PopupCenter() (around line 14595):
"scrollbars=yes, width=" + w + ", height=" + h + ", top=" + top + ", left=" + left
iOS WebKit is stricter than desktop browsers about the features string format. The spaces after commas cause the entire window.open() call to fail. Desktop browsers tolerate it.
3. popup.document.body is not synchronously available on iOS
Immediately after window.open() in PlexOAuth():
$(plex_oauth_window.document.body).html(plex_oauth_loader);
On a freshly-opened popup, iOS does not have document.body ready synchronously. This throws, the uncaught exception kills the click handler, and the PIN fetch never starts. Desktop WebKit/Blink provide document.body synchronously.
Additionally, PopupCenter() calls newWindow.focus() without checking whether newWindow is null, which would throw on any browser where the popup was blocked.
Proposed fix
Three minimal edits to functions.js. I've been running this locally for a few days and it fully resolves iPad Plex OAuth without changing desktop behavior.
Edit 1 — PopupCenter(), features string
Replace:
"scrollbars=yes, width=" +
w +
", height=" +
h +
", top=" +
top +
", left=" +
left
With:
"scrollbars=yes,width=" +
w +
",height=" +
h +
",top=" +
top +
",left=" +
left
Edit 2 — PopupCenter(), null-guard .focus()
Replace:
if (window.focus) {
newWindow.focus();
}
With:
if (newWindow && window.focus) {
newWindow.focus();
}
Edit 3 — PlexOAuth(), use about:blank and guard body write
Replace:
plex_oauth_window = PopupCenter("", "Plex-OAuth", 600, 700);
$(plex_oauth_window.document.body).html(plex_oauth_loader);
With:
plex_oauth_window = PopupCenter("about:blank", "Plex-OAuth", 600, 700);
if (plex_oauth_window && plex_oauth_window.document) {
try { plex_oauth_window.document.write(plex_oauth_loader); } catch (e) {}
}
Repro steps
- Set up Organizr with Plex OAuth as the auth method.
- Open Organizr on an iPad in Brave.
- Tap Login with Plex.
- Observe: nothing happens. No popup, no error, no network activity to plex.tv/api/v2/pins.
- Confirm via an in-page JS console (e.g. the
eruda bookmarklet) that window.open("") returns null and/or that .document.body access throws.
Happy to open a PR with these three edits if it would help.
Clicking Login with Plex using Brave on my iPad does nothing. No popup opens, no error is shown to the user, and the polling loop never starts. The same Organizr instance works correctly in desktop browsers (Brave, Chrome, Firefox, Safari on macOS).
Environment
organizr/organizr:latestRoot cause
Three iOS WebKit quirks combine to kill the click handler before the PIN fetch ever runs. All three are in
functions.js:1.
window.open("")is rejected on iOSIn
PlexOAuth()(around line 14707):iOS WebKit silently refuses
window.open()with an empty-string URL. Using"about:blank"is accepted.2. Features string with spaces is rejected
In
PopupCenter()(around line 14595):iOS WebKit is stricter than desktop browsers about the features string format. The spaces after commas cause the entire
window.open()call to fail. Desktop browsers tolerate it.3.
popup.document.bodyis not synchronously available on iOSImmediately after
window.open()inPlexOAuth():On a freshly-opened popup, iOS does not have
document.bodyready synchronously. This throws, the uncaught exception kills the click handler, and the PIN fetch never starts. Desktop WebKit/Blink providedocument.bodysynchronously.Additionally,
PopupCenter()callsnewWindow.focus()without checking whethernewWindowis null, which would throw on any browser where the popup was blocked.Proposed fix
Three minimal edits to
functions.js. I've been running this locally for a few days and it fully resolves iPad Plex OAuth without changing desktop behavior.Edit 1 —
PopupCenter(), features stringReplace:
With:
Edit 2 —
PopupCenter(), null-guard.focus()Replace:
With:
Edit 3 —
PlexOAuth(), useabout:blankand guard body writeReplace:
With:
Repro steps
erudabookmarklet) thatwindow.open("")returnsnulland/or that.document.bodyaccess throws.Happy to open a PR with these three edits if it would help.