Skip to content

Plex OAuth login button silently fails on iPad / iOS WebKit w/ Brave Browser #2057

Description

@feldorn

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

  1. Set up Organizr with Plex OAuth as the auth method.
  2. Open Organizr on an iPad in Brave.
  3. Tap Login with Plex.
  4. Observe: nothing happens. No popup, no error, no network activity to plex.tv/api/v2/pins.
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions