Add audience parameter to OAuth 2

Closes https://feedback.yaak.app/p/how-do-i-send-an-audience-using-oauth2
This commit is contained in:
Gregory Schier
2025-05-16 07:17:22 -07:00
parent 8c0f889dd2
commit 9615d3e29b
6 changed files with 26 additions and 0 deletions

View File

@@ -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<AccessTokenRawResponse> {
@@ -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 });

View File

@@ -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 },

View File

@@ -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,

View File

@@ -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<AccessToken> {
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));
}

View File

@@ -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<AccessToken> {
@@ -40,6 +42,7 @@ export async function getPassword(
clientId,
clientSecret,
scope,
audience,
grantType: 'password',
credentialsInBody,
params: [

View File

@@ -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 {