From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 9D92F1FF142 for ; Tue, 21 Apr 2026 14:03:17 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id EFDD21F47C; Tue, 21 Apr 2026 14:00:45 +0200 (CEST) From: Arthur Bied-Charreton To: pbs-devel@lists.proxmox.com, pve-devel@lists.proxmox.com Subject: [PATCH proxmox-widget-toolkit v4 12/24] utils: oauth2: Add callback handler Date: Tue, 21 Apr 2026 13:59:45 +0200 Message-ID: <20260421115957.402589-13-a.bied-charreton@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260421115957.402589-1-a.bied-charreton@proxmox.com> References: <20260421115957.402589-1-a.bied-charreton@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.120 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Message-ID-Hash: 3Y6CN5IEBUHYPFBEHUTIQAYGIU25VY3J X-Message-ID-Hash: 3Y6CN5IEBUHYPFBEHUTIQAYGIU25VY3J X-MailFrom: abied-charreton@jett.proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox Backup Server development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- src/Utils.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/Utils.js b/src/Utils.js index ceed4c8..87d322b 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -1812,6 +1812,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 && scope && 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