From 26c8d22d10698709204d7377787632c48063def1 Mon Sep 17 00:00:00 2001 From: Ryan Hartje Date: Tue, 24 Jun 2025 08:02:35 -0500 Subject: [PATCH] add optional audience to oauth2 client credentials flow --- db/old_migrations/patch-monitor-oauth-cc.sql | 3 +++ server/model/monitor.js | 3 ++- server/server.js | 1 + server/util-server.js | 17 +++++++++++------ src/pages/EditMonitor.vue | 4 ++++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/db/old_migrations/patch-monitor-oauth-cc.sql b/db/old_migrations/patch-monitor-oauth-cc.sql index f33e95298..54a26c493 100644 --- a/db/old_migrations/patch-monitor-oauth-cc.sql +++ b/db/old_migrations/patch-monitor-oauth-cc.sql @@ -13,6 +13,9 @@ ALTER TABLE monitor ALTER TABLE monitor ADD oauth_scopes TEXT default null; +ALTER TABLE monitor + ADD oauth_audience TEXT default null; + ALTER TABLE monitor ADD oauth_auth_method TEXT default null; diff --git a/server/model/monitor.js b/server/model/monitor.js index c9844a55d..a301c8059 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -181,6 +181,7 @@ class Monitor extends BeanModel { oauth_client_secret: this.oauth_client_secret, oauth_token_url: this.oauth_token_url, oauth_scopes: this.oauth_scopes, + oauth_audience: this.oauth_audience, oauth_auth_method: this.oauth_auth_method, pushToken: this.pushToken, databaseConnectionString: this.databaseConnectionString, @@ -1746,7 +1747,7 @@ class Monitor extends BeanModel { */ async makeOidcTokenClientCredentialsRequest() { log.debug("monitor", `[${this.name}] The oauth access-token undefined or expired. Requesting a new token`); - const oAuthAccessToken = await getOidcTokenClientCredentials(this.oauth_token_url, this.oauth_client_id, this.oauth_client_secret, this.oauth_scopes, this.oauth_auth_method); + const oAuthAccessToken = await getOidcTokenClientCredentials(this.oauth_token_url, this.oauth_client_id, this.oauth_client_secret, this.oauth_scopes, this.oauth_audience, this.oauth_auth_method); if (this.oauthAccessToken?.expires_at) { log.debug("monitor", `[${this.name}] Obtained oauth access-token. Expires at ${new Date(this.oauthAccessToken?.expires_at * 1000)}`); } else { diff --git a/server/server.js b/server/server.js index 5b2f41a2e..b7025464b 100644 --- a/server/server.js +++ b/server/server.js @@ -802,6 +802,7 @@ let needSetup = false; bean.oauth_auth_method = monitor.oauth_auth_method; bean.oauth_token_url = monitor.oauth_token_url; bean.oauth_scopes = monitor.oauth_scopes; + bean.oauth_audience = monitor.oauth_audience; bean.tlsCa = monitor.tlsCa; bean.tlsCert = monitor.tlsCert; bean.tlsKey = monitor.tlsKey; diff --git a/server/util-server.js b/server/util-server.js index 4cc833330..9eec5148a 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -57,7 +57,7 @@ exports.initJWTSecret = async () => { }; /** - * Decodes a jwt and returns the payload portion without verifying the jqt. + * Decodes a jwt and returns the payload portion without verifying the jwt. * @param {string} jwt The input jwt as a string * @returns {object} Decoded jwt payload object */ @@ -66,17 +66,18 @@ exports.decodeJwt = (jwt) => { }; /** - * Gets a Access Token form a oidc/oauth2 provider - * @param {string} tokenEndpoint The token URI form the auth service provider + * Gets an Access Token from an oidc/oauth2 provider + * @param {string} tokenEndpoint The token URI from the auth service provider * @param {string} clientId The oidc/oauth application client id * @param {string} clientSecret The oidc/oauth application client secret - * @param {string} scope The scope the for which the token should be issued for - * @param {string} authMethod The method on how to sent the credentials. Default client_secret_basic + * @param {string} scope The scope(s) for which the token should be issued for + * @param {string} authMethod The method used to send the credentials. Default client_secret_basic * @returns {Promise} TokenSet promise if the token request was successful */ -exports.getOidcTokenClientCredentials = async (tokenEndpoint, clientId, clientSecret, scope, authMethod = "client_secret_basic") => { +exports.getOidcTokenClientCredentials = async (tokenEndpoint, clientId, clientSecret, scope, audience, authMethod = "client_secret_basic") => { const oauthProvider = new oidc.Issuer({ token_endpoint: tokenEndpoint }); let client = new oauthProvider.Client({ + issuer: audience, client_id: clientId, client_secret: clientSecret, token_endpoint_auth_method: authMethod @@ -90,6 +91,10 @@ exports.getOidcTokenClientCredentials = async (tokenEndpoint, clientId, clientSe if (scope) { grantParams.scope = scope; } + + if (audience) { + grantParams.audience = audience; + } return await client.grant(grantParams); }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 0d628895d..1b7af4184 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -1025,6 +1025,10 @@ +
+ + +