Share via

Popup Login flow not working since microsoft blocked windows opener unexpectedly

Collection Team 5 Reputation points
2026-02-27T09:00:10.9633333+00:00

We are facing issues with https://login.windows.net/common/OAuth2/authorize?resource=https://manage.office.com since the resource is giving response header as cross-origin-opener-policy : same-origin; report-to="coop-endpoint"due to which window.opener is not working and after successful redirection with microsoft we are unable to get back the auth code back to platform using window.opener.postMessage, this issue causing the popup window to hang and blocking the whole authorization flow

cross-origin-opener

User's image

Microsoft 365 and Office | Development | Office JavaScript API
0 comments No comments
{count} vote

2 answers

Sort by: Most helpful
  1. Andrea Santi 15 Reputation points
    2026-03-05T11:42:00.2233333+00:00

    TL;DR

    Use BroadcastChannel instead of window.opener — fix is in the last code block below.

    (I want 2 days of my life back.)


    We ran into the exact same issue and spent two days debugging it. Here is what we found and the fix that actually works.

    Microsoft silently deployed Cross-Origin-Opener-Policy: same-origin on login.microsoftonline.com. Still visible in Report-Only mode today (Cross-Origin-Opener-Policy-Report-Only: same-origin). When enforced, the browser does a Browsing Context Group (BCG) switch the moment the popup hits Microsoft's login page — and that permanently kills window.opener. Not temporarily. Permanently. Even after the popup navigates back to your own domain.

    The answer above by suggesting window.opener.postMessage() from your redirect page doesn't work for exactly this reason. The BCG switch doesn't reverse on navigation away from Microsoft's domain — it triggers a second one. opener stays null. @Yuri Leontyev @Robert Tucker-Bays The only thing that works is BroadcastChannel — it doesn't use window references at all:

    // popup
    const ch = new BroadcastChannel('auth-callback');
    ch.postMessage({ type: 'AUTH_SUCCESS', token });
    ch.close(); window.close();
    
    // parent
    const ch = new BroadcastChannel('auth-callback');
    ch.onmessage = (e) => { if (e.data?.type === 'AUTH_SUCCESS') { ch.close(); /* ... */ } };
    

    Supported in every modern browser since ~2016, COOP-immune by design.


    To whoever at Microsoft is reading this: you canary-deployed a breaking change to a production identity provider with no changelog, no deprecation notice, nothing. Users got locked out of production systems. We spent two days looking for the bug in our own code. "Report-only" is not communication — it's a header that developers see only if they happen to be staring at DevTools at the right moment.

    When you enforce this, please put a notice somewhere. The 2 days of my life spent debugging it are already gone — at least spare the next person.

    3 people found this answer helpful.

  2. Teddie-D 12,925 Reputation points Microsoft External Staff Moderator
    2026-02-27T12:09:53.96+00:00

    Hi @Collection Team 

    Thank you for posting your question in the Microsoft Q&A forum. 

    Please note that our forum is a public platform, and we will modify your image to hide your personal information in the description. Kindly ensure that you hide any personal or organizational information the next time you post an error or other details to protect personal data.

    You’re running into a browser security change, not an OAuth issue. When Microsoft login pages send the header Cross-Origin-Opener-Policy: same-origin; report-to="coop-endpoint", modern browsers place that page in a separate browsing context group. As a result, window.opener is intentionally set to null for cross-origin popups, so calls like window.opener.postMessage(...) stop working after the redirect from login.windows.net or login.microsoftonline.com

    This behavior is enforced by the browser as part of the Cross-Origin-Opener-Policy (COOP) specification and cannot be overridden by your application.

    Here are some options you may consider: 

    1.Use redirect flow instead of popup 

    -Redirect the main window with window.location.href = authorizeUrl .

    -User signs in on Microsoft’s domain.  

    -Microsoft redirects back to your redirect URI.  

    -Your app reads the authorization code from the query string.  

    -Exchange the authorization code for tokens.  

    -This avoids window.opener entirely.  

    2.Use redirect + postMessage from your own redirect page. 

    If you must keep a popup-based experience:

    -Set your redirect URI to a page you control, e.g. https://yourapp.com/auth-callback.html

    -After Microsoft completes authentication, it redirects the popup to that page.

    -Since the page is now on your domain, it can safely execute:

    window.opener.postMessage(authData, "https://yourapp.com");  
    window.close();
    

     Important notes: 

    -The postMessage must originate from your domain, not from Microsoft’s login domain.

    -The redirect page must not send a restrictive COOP header (such as Cross-Origin-Opener-Policy: same-origin), otherwise window.opener will remain unavailable.

    -The popup must not be opened with noopener, as that also nullifies window.opener.

    -The redirect page must be same-origin with the parent window.

    Once the popup navigates away from Microsoft’s isolated page and loads your same-origin redirect page (without COOP isolation), the opener relationship can be available again, allowing postMessage to succeed.

    I hope this helps clarify the behavior and available options.


    If the answer is helpful, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".  

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread. 

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.