The OAuth2 flow triggered by OAuth2._handleFlow redirects to
window.location.origin after successful authorization.

This callback handler detects whether a login was triggered as the
result of such a redirect based on the presence of the code, scope and
state URL parameters. It then communicates the authorization results
back to the parent window.

Windows opened via scripts are normally also script-closable, however
this property is lost after a redirect, which is why handleCallback
relies on its parent window to kill it after it receives the data it
needs.

Signed-off-by: Arthur Bied-Charreton <[email protected]>
---
 src/Utils.js | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/src/Utils.js b/src/Utils.js
index 5b951ce..17fd238 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -1839,6 +1839,37 @@ Ext.define('Proxmox.OAuth2', {
             });
         });
     },
+
+    handleCallback: function (params) {
+        let code = params.get('code');
+        let scope = params.get('scope');
+        let state = params.get('state');
+
+        // If true, this login was triggered as the result of an OAuth2 
redirect. If it
+        // comes from the SMTP XOAUTH2 authorization flow, the state parameter 
should contain
+        // a UUID identifying a BroadcastChannel, prefixed with 'oauth2_'. The 
initiator of
+        // the OAuth2 flow (see _handleFlow) expects to receive the resulting 
code via this
+        // BroadcastChannel.
+        //
+        // Since we got here through a redirect, this window is not 
script-closable, and we rely
+        // on the parent window to close it in its BroadcastChannel's message 
handler.
+        if (code && state) {
+            try {
+                let { channelName } = JSON.parse(decodeURIComponent(state));
+                if (!channelName || !channelName.startsWith('oauth2_')) {
+                    // Ignore OpenID logins
+                    return false;
+                }
+                let bc = new BroadcastChannel(channelName);
+                bc.postMessage({ code, scope });
+                return true;
+            } catch (_) {
+                // There is nothing we can really do here, JSON.parse failed 
so we do not
+                // know the name of the channel we should communicate errors 
back through.
+            }
+        }
+        return false;
+    },
 });
 
 Ext.define('Proxmox.Async', {
-- 
2.47.3



Reply via email to