From 9615d3e29bb2118d02758301653d0e921b7850df Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Fri, 16 May 2025 07:17:22 -0700 Subject: [PATCH] Add audience parameter to OAuth 2 Closes https://feedback.yaak.app/p/how-do-i-send-an-audience-using-oauth2 --- plugins/auth-oauth2/src/getAccessToken.ts | 3 +++ plugins/auth-oauth2/src/grants/authorizationCode.ts | 4 ++++ plugins/auth-oauth2/src/grants/clientCredentials.ts | 3 +++ plugins/auth-oauth2/src/grants/implicit.ts | 3 +++ plugins/auth-oauth2/src/grants/password.ts | 3 +++ plugins/auth-oauth2/src/index.ts | 10 ++++++++++ 6 files changed, 26 insertions(+) diff --git a/plugins/auth-oauth2/src/getAccessToken.ts b/plugins/auth-oauth2/src/getAccessToken.ts index 6d04a379..0304916f 100644 --- a/plugins/auth-oauth2/src/getAccessToken.ts +++ b/plugins/auth-oauth2/src/getAccessToken.ts @@ -6,6 +6,7 @@ export async function getAccessToken( ctx: Context, { accessTokenUrl, scope, + audience, params, grantType, credentialsInBody, @@ -17,6 +18,7 @@ export async function getAccessToken( grantType: string; accessTokenUrl: string; scope: string | null; + audience: string | null; credentialsInBody: boolean; params: HttpUrlParameter[]; }): Promise { @@ -39,6 +41,7 @@ export async function getAccessToken( }; if (scope) httpRequest.body!.form.push({ name: 'scope', value: scope }); + if (scope) httpRequest.body!.form.push({ name: 'audience', value: audience }); if (credentialsInBody) { httpRequest.body!.form.push({ name: 'client_id', value: clientId }); diff --git a/plugins/auth-oauth2/src/grants/authorizationCode.ts b/plugins/auth-oauth2/src/grants/authorizationCode.ts index 247a3a72..c9400d6b 100644 --- a/plugins/auth-oauth2/src/grants/authorizationCode.ts +++ b/plugins/auth-oauth2/src/grants/authorizationCode.ts @@ -19,6 +19,7 @@ export async function getAuthorizationCode( redirectUri, scope, state, + audience, credentialsInBody, pkce, }: { @@ -29,6 +30,7 @@ export async function getAuthorizationCode( redirectUri: string | null; scope: string | null; state: string | null; + audience: string | null; credentialsInBody: boolean; pkce: { challengeMethod: string | null; @@ -53,6 +55,7 @@ export async function getAuthorizationCode( if (redirectUri) authorizationUrl.searchParams.set('redirect_uri', redirectUri); if (scope) authorizationUrl.searchParams.set('scope', scope); if (state) authorizationUrl.searchParams.set('state', state); + if (audience) authorizationUrl.searchParams.set('audience', audience); if (pkce) { const verifier = pkce.codeVerifier || createPkceCodeVerifier(); const challengeMethod = pkce.challengeMethod || DEFAULT_PKCE_METHOD; @@ -95,6 +98,7 @@ export async function getAuthorizationCode( clientId, clientSecret, scope, + audience, credentialsInBody, params: [ { name: 'code', value: code }, diff --git a/plugins/auth-oauth2/src/grants/clientCredentials.ts b/plugins/auth-oauth2/src/grants/clientCredentials.ts index 6fb8e6e4..9543d9b7 100644 --- a/plugins/auth-oauth2/src/grants/clientCredentials.ts +++ b/plugins/auth-oauth2/src/grants/clientCredentials.ts @@ -10,12 +10,14 @@ export async function getClientCredentials( clientId, clientSecret, scope, + audience, credentialsInBody, }: { accessTokenUrl: string; clientId: string; clientSecret: string; scope: string | null; + audience: string | null; credentialsInBody: boolean; }, ) { @@ -29,6 +31,7 @@ export async function getClientCredentials( const response = await getAccessToken(ctx, { grantType: 'client_credentials', accessTokenUrl, + audience, clientId, clientSecret, scope, diff --git a/plugins/auth-oauth2/src/grants/implicit.ts b/plugins/auth-oauth2/src/grants/implicit.ts index 15105b0f..a54d1964 100644 --- a/plugins/auth-oauth2/src/grants/implicit.ts +++ b/plugins/auth-oauth2/src/grants/implicit.ts @@ -11,6 +11,7 @@ export function getImplicit( redirectUri, scope, state, + audience, }: { authorizationUrl: string; responseType: string; @@ -18,6 +19,7 @@ export function getImplicit( redirectUri: string | null; scope: string | null; state: string | null; + audience: string | null; }, ) :Promise { return new Promise(async (resolve, reject) => { @@ -34,6 +36,7 @@ export function getImplicit( if (redirectUri) authorizationUrl.searchParams.set('redirect_uri', redirectUri); if (scope) authorizationUrl.searchParams.set('scope', scope); if (state) authorizationUrl.searchParams.set('state', state); + if (audience) authorizationUrl.searchParams.set('audience', audience); if (responseType.includes('id_token')) { authorizationUrl.searchParams.set('nonce', String(Math.floor(Math.random() * 9999999999999) + 1)); } diff --git a/plugins/auth-oauth2/src/grants/password.ts b/plugins/auth-oauth2/src/grants/password.ts index f1a685da..2192345f 100644 --- a/plugins/auth-oauth2/src/grants/password.ts +++ b/plugins/auth-oauth2/src/grants/password.ts @@ -13,6 +13,7 @@ export async function getPassword( username, password, credentialsInBody, + audience, scope, }: { accessTokenUrl: string; @@ -21,6 +22,7 @@ export async function getPassword( username: string; password: string; scope: string | null; + audience: string | null; credentialsInBody: boolean; }, ): Promise { @@ -40,6 +42,7 @@ export async function getPassword( clientId, clientSecret, scope, + audience, grantType: 'password', credentialsInBody, params: [ diff --git a/plugins/auth-oauth2/src/index.ts b/plugins/auth-oauth2/src/index.ts index 60ae2cf3..731bf291 100644 --- a/plugins/auth-oauth2/src/index.ts +++ b/plugins/auth-oauth2/src/index.ts @@ -156,6 +156,12 @@ export const plugin: PluginDefinition = { optional: true, dynamic: hiddenIfNot(['authorization_code', 'implicit']), }, + { + type: 'text', + name: 'audience', + label: 'Audience', + optional: true, + }, { type: 'checkbox', name: 'usePkce', @@ -258,6 +264,7 @@ export const plugin: PluginDefinition = { clientSecret: stringArg(values, 'clientSecret'), redirectUri: stringArgOrNull(values, 'redirectUri'), scope: stringArgOrNull(values, 'scope'), + audience: stringArgOrNull(values, 'audience'), state: stringArgOrNull(values, 'state'), credentialsInBody, pkce: values.usePkce ? { @@ -273,6 +280,7 @@ export const plugin: PluginDefinition = { redirectUri: stringArgOrNull(values, 'redirectUri'), responseType: stringArg(values, 'responseType'), scope: stringArgOrNull(values, 'scope'), + audience: stringArgOrNull(values, 'audience'), state: stringArgOrNull(values, 'state'), }); } else if (grantType === 'client_credentials') { @@ -282,6 +290,7 @@ export const plugin: PluginDefinition = { clientId: stringArg(values, 'clientId'), clientSecret: stringArg(values, 'clientSecret'), scope: stringArgOrNull(values, 'scope'), + audience: stringArgOrNull(values, 'audience'), credentialsInBody, }); } else if (grantType === 'password') { @@ -293,6 +302,7 @@ export const plugin: PluginDefinition = { username: stringArg(values, 'username'), password: stringArg(values, 'password'), scope: stringArgOrNull(values, 'scope'), + audience: stringArgOrNull(values, 'audience'), credentialsInBody, }); } else {