From: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
To: pve-devel@lists.proxmox.com, pbs-devel@lists.proxmox.com
Subject: [PATCH docs/manager/proxmox{,-perl-rs,-widget-toolkit,-backup} v5 00/27] fix #7238: Add XOAUTH2 authentication support for SMTP notification targets
Date: Tue, 5 May 2026 10:32:21 +0200 [thread overview]
Message-ID: <20260505083248.36450-1-a.bied-charreton@proxmox.com> (raw)
This series adds XOAUTH2 support for SMTP notification targets in PVE
and PBS, motivated by Microsoft's upcoming deprecation of basic
authentication for SMTP [0]. Google and Microsoft are supported as
OAuth2 providers.
The main challenge is the OAuth2 refresh tokens management. The
implementations differ from provider to provider, and for Microsoft
specifically, the token needs to be writable by proxmox-notify, since
Microsoft 365/Copilot/... OAuth2 rotates it at every use.
This series solves this by introducing state files, managed entirely
in proxmox-notify. Each SMTP endpoint gets its own. Tokens are
refreshed proactively in PVE's and PBS's respective daily update jobs
under a notification config lock, in order to prevent concurrent
config/state file updates.
Provider-specific stuff:
* Google: The token is refreshed in-place, meaning its lifetime is
extended at every use without it being *actually* rotated [1]. The
token in the state file does not change. Only the last_refreshed
timestamp is updated in daily update jobs.
* Microsoft: The token is rotated by Microsoft at each request, and
each token has a fixed lifetime of 90 days [2]. While the
recommendation is to persist the newly issued token right away, we
would need to hold a lock each time a notification is sent in order
to do so safely, and the rotation does not invalidate the old token.
After some off-list discussion (thanks to all involved), we landed on
only persisting the rotated token once a day, under a full
notifications config lock.
For access token requests in proxmox-notify, the oauth2 crate is used
with a custom proxmox-http backend, which makes it easier to take
proxy configs into account and avoids pulling in reqwest.
Endpoints performing the initial authorization code -> refresh token
exchange are added to PVE and PBS. It is not possible to do this
directly from the UI, because Microsoft rejects browser-originated
token requests.
This series requires the following version requirement bumps:
* proxmox-perl-rs -> bumped proxmox-notify
* pve-manager -> bumped proxmox-widget-toolkit and proxmox-perl-rs
* proxmox-backup -> bumped proxmox-widget-toolkit and proxmox-notify
The UI part of the OAuth2 flow is opt-in for consumers, the widget
toolkit may be bumped without bumping all products directly.
Note that this introduces a breaking change in the proxmox-notify API.
Changes since RFC:
https://lore.proxmox.com/pve-devel/20260213160415.609868-1-a.bied-charreton@proxmox.com/
Changes since v1:
https://lore.proxmox.com/pve-devel/20260325131444.366808-1-a.bied-charreton@proxmox.com/
Changes since v2:
https://lore.proxmox.com/pve-devel/20260415070220.100306-1-a.bied-charreton@proxmox.com/
Changes since v3:
https://lore.proxmox.com/pve-devel/20260421115957.402589-1-a.bied-charreton@proxmox.com/
Changes since v4:
pve-docs, proxmox-backup/docs:
* Remove the `/etc/hosts` hack for Google redirect URIs
* Use example.com as example domain
* Improve wording and fix typo
* Document that from-address is used as SMTP authentication
identity
proxmox-notify:
* Do not persist new refresh tokens while sending notification
* Replace unwrap with `if let Some(...)` in State::save
* Improve some doc comments
* Create state files' parent directories with different options
than the state file itself
proxmox-backup,pve-manager:
* Lock notifications config when updating notifications state
in daily update jobs
* Move initial authorization code -> refresh token exchange to
the backend instead of hitting provider endpoints directly
from the browser (Azure AD rejects browser-originated token
requests)
proxmox-widget-toolkit:
* Reject before making the refresh token request if the
authorization window does not return an authorization
code
* Delete `oauth2-refresh-token` if empty to prevent sending
Some(""), which would overwrite an existing refresh token
* Add refreshTokenUrl config field to SmtpEditPanel
[0] https://techcommunity.microsoft.com/blog/exchange/updated-exchange-online-smtp-auth-basic-authentication-deprecation-timeline/4489835
[1] https://developers.google.com/identity/protocols/oauth2#expiration
[2] https://learn.microsoft.com/en-us/entra/identity-platform/refresh-tokens#token-lifetime
proxmox:
Arthur Bied-Charreton (9):
add oauth2 and ureq to workspace dependencies
notify: smtp: introduce xoauth2 module
notify: smtp: introduce state management
notify: smtp: factor out transport building logic
notify: smtp: update API with OAuth2 parameters
notify: smtp: add API to exchange authorization code for refresh token
notify: smtp: infer auth method for backwards compatibility
notify: smtp: add state handling logic
notify: smtp: add XOAUTH2 authentication support
Cargo.toml | 2 +
proxmox-http/Cargo.toml | 2 +-
proxmox-notify/Cargo.toml | 16 +-
proxmox-notify/debian/control | 66 ++--
proxmox-notify/src/api/common.rs | 19 ++
proxmox-notify/src/api/smtp.rs | 203 ++++++++++--
proxmox-notify/src/context/mod.rs | 13 +
proxmox-notify/src/context/pbs.rs | 24 ++
proxmox-notify/src/context/pve.rs | 26 +-
proxmox-notify/src/context/test.rs | 23 ++
proxmox-notify/src/endpoints/smtp.rs | 236 ++++++++++++--
proxmox-notify/src/endpoints/smtp/xoauth2.rs | 310 +++++++++++++++++++
proxmox-notify/src/lib.rs | 40 ++-
proxmox-openid/Cargo.toml | 2 +-
14 files changed, 885 insertions(+), 97 deletions(-)
create mode 100644 proxmox-notify/src/endpoints/smtp/xoauth2.rs
proxmox-perl-rs:
Arthur Bied-Charreton (3):
pve-rs: notify: smtp: add OAuth2 parameters to bindings
pve-rs: notify: add binding for triggering state refresh
pve-rs: notify: add binding for initial OAuth2 refresh token exchange
common/src/bindings/notify.rs | 102 +++++++++++++++++-----------------
1 file changed, 50 insertions(+), 52 deletions(-)
proxmox-widget-toolkit:
Arthur Bied-Charreton (3):
utils: add OAuth2 flow handlers
utils: oauth2: add callback handler
notifications: add opt-in OAuth2 support for SMTP targets
src/Utils.js | 130 ++++++++++++++++
src/panel/SmtpEditPanel.js | 266 ++++++++++++++++++++++++++++++---
src/window/EndpointEditBase.js | 2 +
3 files changed, 374 insertions(+), 24 deletions(-)
pve-manager:
Arthur Bied-Charreton (5):
notifications: smtp: api: add XOAUTH2 parameters
notifications: add endpoint for initial OAuth2 refresh token exchange
pveupdate: refresh notification targets' OAuth2 state
login: handle OAuth2 callback
fix #7238: notifications: smtp: add XOAUTH2 support
PVE/API2/Cluster/Notifications.pm | 179 ++++++++++++++++++++++++++----
bin/pveupdate | 13 +++
www/manager6/Utils.js | 11 ++
www/manager6/Workspace.js | 2 +
4 files changed, 182 insertions(+), 23 deletions(-)
proxmox-backup:
Arthur Bied-Charreton (6):
notifications: add XOAUTH2 parameters to endpoints
notifications: add endpoint for initial OAuth2 refresh token exchange
login: handle OAuth2 callback
fix #7238: notifications: smtp: add XOAUTH2 support
daily-update: refresh OAuth2 state for SMTP notification endpoints
notifications: add OAuth2 section to SMTP targets docs
docs/notifications.rst | 89 ++++++++++++++++++++++-
src/api2/config/notifications/mod.rs | 1 +
src/api2/config/notifications/smtp.rs | 101 +++++++++++++++++++++++++-
src/bin/proxmox-daily-update.rs | 11 +++
www/Application.js | 4 +-
www/OnlineHelpInfo.js | 8 ++
www/Utils.js | 2 +
7 files changed, 210 insertions(+), 6 deletions(-)
pve-docs:
Arthur Bied-Charreton (1):
notifications: add OAuth2 section to SMTP targets docs
notifications.adoc | 88 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
Summary over all repositories:
30 files changed, 1789 insertions(+), 202 deletions(-)
--
Generated by murpp 0.11.0
next reply other threads:[~2026-05-05 8:34 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-05 8:32 Arthur Bied-Charreton [this message]
2026-05-05 8:32 ` [PATCH proxmox v5 01/27] add oauth2 and ureq to workspace dependencies Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 02/27] notify: smtp: introduce xoauth2 module Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 03/27] notify: smtp: introduce state management Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 04/27] notify: smtp: factor out transport building logic Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 05/27] notify: smtp: update API with OAuth2 parameters Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 06/27] notify: smtp: add API to exchange authorization code for refresh token Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 07/27] notify: smtp: infer auth method for backwards compatibility Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 08/27] notify: smtp: add state handling logic Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox v5 09/27] notify: smtp: add XOAUTH2 authentication support Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-perl-rs v5 10/27] pve-rs: notify: smtp: add OAuth2 parameters to bindings Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-perl-rs v5 11/27] pve-rs: notify: add binding for triggering state refresh Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-perl-rs v5 12/27] pve-rs: notify: add binding for initial OAuth2 refresh token exchange Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-widget-toolkit v5 13/27] utils: add OAuth2 flow handlers Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-widget-toolkit v5 14/27] utils: oauth2: add callback handler Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-widget-toolkit v5 15/27] notifications: add opt-in OAuth2 support for SMTP targets Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH pve-manager v5 16/27] notifications: smtp: api: add XOAUTH2 parameters Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH pve-manager v5 17/27] notifications: add endpoint for initial OAuth2 refresh token exchange Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH pve-manager v5 18/27] pveupdate: refresh notification targets' OAuth2 state Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH pve-manager v5 19/27] login: handle OAuth2 callback Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH pve-manager v5 20/27] fix #7238: notifications: smtp: add XOAUTH2 support Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-backup v5 21/27] notifications: add XOAUTH2 parameters to endpoints Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-backup v5 22/27] notifications: add endpoint for initial OAuth2 refresh token exchange Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-backup v5 23/27] login: handle OAuth2 callback Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-backup v5 24/27] fix #7238: notifications: smtp: add XOAUTH2 support Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-backup v5 25/27] daily-update: refresh OAuth2 state for SMTP notification endpoints Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH proxmox-backup v5 26/27] notifications: add OAuth2 section to SMTP targets docs Arthur Bied-Charreton
2026-05-05 8:32 ` [PATCH pve-docs v5 27/27] " Arthur Bied-Charreton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260505083248.36450-1-a.bied-charreton@proxmox.com \
--to=a.bied-charreton@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox