Expose endpoint under /config/notifications/smtp-oauth2-token to exchange the initial authorization code for a refresh token.
Azure AD's "Web" client type, which we require in order to be able to keep getting new access tokens in the backend without requiring re-authorization by users, rejects browser-originated token requests, so this must run on the backend. Signed-off-by: Arthur Bied-Charreton <[email protected]> --- src/api2/config/notifications/mod.rs | 1 + src/api2/config/notifications/smtp.rs | 65 ++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/api2/config/notifications/mod.rs b/src/api2/config/notifications/mod.rs index 8ebd3e4eb..07f6e0f90 100644 --- a/src/api2/config/notifications/mod.rs +++ b/src/api2/config/notifications/mod.rs @@ -29,6 +29,7 @@ const SUBDIRS: SubdirMap = &sorted!([ ("endpoints", &ENDPOINT_ROUTER), ("matcher-fields", &FIELD_ROUTER), ("matcher-field-values", &VALUE_ROUTER), + ("smtp-oauth2-token", &smtp::OAUTH2_TOKEN_ROUTER), ("targets", &targets::ROUTER), ("matchers", &matchers::ROUTER), ]); diff --git a/src/api2/config/notifications/smtp.rs b/src/api2/config/notifications/smtp.rs index 4d88bd659..0de23241f 100644 --- a/src/api2/config/notifications/smtp.rs +++ b/src/api2/config/notifications/smtp.rs @@ -5,7 +5,7 @@ use proxmox_notify::endpoints::smtp::{ DeleteableSmtpProperty, SmtpConfig, SmtpConfigUpdater, SmtpPrivateConfig, SmtpPrivateConfigUpdater, }; -use proxmox_notify::schema::ENTITY_NAME_SCHEMA; +use proxmox_notify::{endpoints::smtp::SmtpAuthMethod, schema::ENTITY_NAME_SCHEMA}; use proxmox_router::{Permission, Router, RpcEnvironment}; use proxmox_schema::api; @@ -219,3 +219,66 @@ pub const ROUTER: Router = Router::new() .get(&API_METHOD_LIST_ENDPOINTS) .post(&API_METHOD_ADD_ENDPOINT) .match_all("name", &ITEM_ROUTER); + +#[api( + protected: true, + input: { + properties: { + "auth-method": { + type: SmtpAuthMethod, + }, + "client-id": { + description: "OAuth2 client ID.", + type: String, + }, + "client-secret": { + description: "OAuth2 client secret.", + type: String, + }, + "tenant-id": { + description: "Microsoft tenant ID (required for microsoft-oauth2).", + type: String, + optional: true, + }, + "authorization-code": { + description: "Authorization code returned by the IdP.", + type: String, + }, + "redirect-uri": { + description: "Redirect URI used in the authorization request.", + type: String, + }, + }, + }, + returns: { + description: "OAuth2 refresh token", + type: String, + }, + access: { + permission: &Permission::Privilege(&["system", "notifications"], PRIV_SYS_MODIFY, false), + }, +)] +/// Exchange an OAuth2 authorization code for a refresh token. +/// +/// The token request is performed server-side so that providers (notably Azure AD +/// Web app registrations) which forbid cross-origin token redemption accept it. +pub fn exchange_oauth2_code( + auth_method: SmtpAuthMethod, + client_id: String, + client_secret: String, + tenant_id: Option<String>, + authorization_code: String, + redirect_uri: String, +) -> Result<String, Error> { + proxmox_notify::api::smtp::exchange_oauth2_code( + auth_method, + client_id, + client_secret, + tenant_id, + authorization_code, + redirect_uri, + ) + .map_err(Into::into) +} + +pub const OAUTH2_TOKEN_ROUTER: Router = Router::new().post(&API_METHOD_EXCHANGE_OAUTH2_CODE); -- 2.47.3
