[PATCH proxmox-widget-toolkit v3 12/23] utils: oauth2: Add callback handler

Arthur Bied-Charreton
2026-04-15T07:02:56Z

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 <a.bied-charreton@proxmox.com>
---
src/Utils.js | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/src/Utils.js b/src/Utils.js
index ceed4c8..f4e2cd1 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -1812,6 +1812,31 @@ 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, which
+ // should contain a UUID identifying a BroadcastChannel in the state parameter.
+ // 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 && scope && state) {
+ try {
+ let { channelName } = JSON.parse(decodeURIComponent(state));
+ let bc = new BroadcastChannel(channelName);
+ bc.postMessage({ code, scope });
+ } 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.
+ }
+ }
+ }
});

Ext.define('Proxmox.Async', {
--
2.47.3