Opening OAuth2 Login Window In an Modal

I’m creating a number of OAuth2 logins over the coming weeks, and I’d like to be a be able open the login window from the 3rd party app in a modal rather than in a separate tab.

Does anyone have any experience of doing this?

My personal view is that it’s a bad idea for a number of reasons (e.g. CORS, Responsiveness) and you should look at using JavaScript windows instead. It’s as simple as adding an onclick event and you can control the popup window size and location.

e.g.

onclick=“window.open(‘https://login.xero.com/identity/connect/authorize?response_type=code&client_id=XXXXX&redirect_uri=https://xxx&scope=offline_access accounting.transactions accounting.contacts accounting.settings&state=x’,‘popup’,‘width=600,height=600’); return false;”

3 Likes

This can be done, and it certainly solves the anoying back-and-forth navigation issue aswell (a quite common and known issue to occur in OAuth Flows) i.e. after users authenticates, they might navigate back to the original application manually/accidentally using the Browser Back button, in such a case the user is taken to the login screen of the IDP.

Sharing a code snippet that you can use in your login page to call on click of the login button, supply the attribute for the url to your IdP when calling the function

<dmx-value id="var_preloader" dmx-bind:value="0"></dmx-value>
<dmx-preloader id="loader" spinner="circle" preview="true" dmx-show="var_preloader.value"></dmx-preloader>
<script>
    function Redirect(t) {
        // Get the current domain of the parent window
        var initialDomain = window.location.hostname;

        // Get the dimensions of the parent window
        var screenWidth = window.innerWidth;
        var screenHeight = window.innerHeight;

        // Define the dimensions for the popup window based on the screen size
        var width = screenWidth < 500 ? screenWidth : 500; // Set the maximum width to 500
        var height = screenHeight < 800 ? screenHeight : 800; // Set the maximum height to 800

        // Calculate the position to center the popup window on the screen
        var left = (window.innerWidth - width) / 2;
        var top = (window.innerHeight - height) / 2;

        // Define the features for the popup window (e.g., dimensions and position)
        var features = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top;

        // Show a preloader while the OAuth process is in progress
        dmx.parse("content.var_preloader.setValue(1)");

        // Define the popup variable in a broader scope
        var popup;

        // Open the popup window with the OAuth URL
        popup = window.open(t, "OAuthPopup", features);

        // Set up an interval to periodically check if the popup is closed
        var popupClosedInterval = setInterval(function () {
            if (popup.window && !popup.closed) {
                try {
                    // Check if the popup's hostname matches the parent's hostname
                    if (popup.location.hostname === initialDomain) {
                        // Get query parameters from the popup's URL
                        var popupURL = new URL(popup.location.href);
                        var queryParameters = popupURL.search;

                        // Close the popup and update the parent window with the query parameters
                        popup.close();
                        dmx.parse("content.var_preloader.setValue(0)");
                        setTimeout(function () {
                            // Redirect to the parent window with query parameters and force a reload
                            window.location.assign(window.location.href + queryParameters);
                            location.reload(true);
                        }, 1000);

                        // Stop checking once done
                        clearInterval(popupClosedInterval);
                    }
                } catch (error) {
                    // Handle any potential cross-origin errors (commented out for now)
                }
            } else {
                // Stop checking if the popup is closed
                clearInterval(popupClosedInterval);
                dmx.parse("content.var_preloader.setValue(0)");
            }
        }, 100);
    }
</script>
1 Like

Thank you @scalaris and @Roney_Dsilva:pray:

Much appreciated… :tada:

I will have a play with these methods! :rocket: