"window.opener" becomes null after redirecting back to the main page from Facebook OAuth on Android browsers
I am implementing Facebook OAuth for user sign-in following facebook-login/guides/advanced/manual-flow. When the user clicks "Sign in with Facebook," a popup window opens at https://my-domain/login, which redirects to Facebook's OAuth URL (e.g., https://www.facebook.com/v21.0/dialog/oauth?...). Initially, window.opener correctly points to the parent window that opened the popup.
However, after the user completes the login (e.g., clicks "Continue as [Username]") and is redirected back to https://my-domain/login, window.opener unexpectedly becomes null. Since window.opener shouldn't become null during this process, this behavior is breaking my implementation, as I rely on window.opener.postMessage() to send the redirect URI back to the main window.
This issue occurs in all Android browsers (e.g., Chrome, Firefox, Opera) but works correctly on desktop browsers. Other OAuth providers like Google, Github, etc. works fine on both Android and Desktop browsers. Facebook works on Desktop browser, but window.opener becomes null in Android browser. In the network tab, I noticed that desktop browsers make requests to www.facebook.com, while Android browsers make calls to m.facebook.com. Why does window.opener become null on Android browsers, and how can I resolve this?
Additional Reproduction Steps:
Enable remote debugging on an Android browser using Chrome DevTools.
Open a new tab and run the following in the Console tab:
window.open(LOGIN_PAGE_URL);
Replace
LOGIN_PAGE_URL
with a site supporting Facebook login (e.g., https://leetcode.com/accounts/login/).In the popup window, run:
window.opener;
It correctly returns the parent window reference.
Click "Sign in with Facebook." On the Facebook login page,
window.opener
still returns the correct reference.Complete the login. After redirecting back to the original page,
window.opener
unexpectedly becomesnull
. Because window.opener becomes null, I am unable to send redirect_uri by doing window.opener.postMessage() from popup window to my opener window.Example code to reproduce the same error:
<!-- Parent window --> <html> <body> <button id="login-btn">Sign in with Facebook</button> <script> document.getElementById("login-btn").onclick = () => { const popup = window.open("https://my-domain/login", "_blank", "width=600,height=600"); window.addEventListener("message", (event) => { if (event.origin === "https://my-domain") { console.log("Received message from popup:", event.data); } }); }; </script> </body> </html> <!-- Popup window --> <html> <body> <script> // Redirects to Facebook login window.location.href = "https://www.facebook.com/v21.0/dialog/oauth?response_type=code%2Cgranted_scopes&client_id=CLIENT_ID&state=STATE_STRING&scope=public_profile%2Cemail%2Cuser_likes&redirect_uri=https://my-domain/login"; // After redirect back from Facebook window.onload = () => { if (window.opener) { window.opener.postMessage({ redirect_uri: window.location.href }, "https://my-domain"); } else { console.error("window.opener is null"); } }; </script> </body> </html>
Client ID can be retrieved by registering a web-app in https://developers.facebook.com/.