Skip to main content

OAuth2 token audience

There are two types of audience concepts in OAuth 2.0 and OpenID Connect:

  • OAuth 2.0 access token audience: OAuth 2.0 access tokens are "internal-facing". In other words, the aud claim of an OAuth 2.0 access token defines the endpoints at which the token can be used.
  • OpenID Connect ID token audience: OpenID Connect ID tokens are "external-facing". The aud claim of an OpenID Connect ID Token defines which clients should accept it.

Add audiences to the client allow list

To specify the intended audiences for an OAuth 2.0 access token, the OAuth 2.0 client needs to proactively define the audiences it needs access to when creating or updating the client. This can be done by including the audience parameter in the client's metadata.

The audience parameter is a list of case-sensitive URLs. The URLs can't contain whitespaces.

{
client_id: "...",
// ..
audience: ["https://api.my-cloud.com/user", "https://some-tenant.my-cloud.com/"],
// ..
}

If you're a developer looking to manage OAuth2 clients, you can find more information in the Manage OAuth2 Clients document.

Audience in Authorization Code, Implicit, and hybrid flows

When performing an OAuth 2.0 Authorization Code Grant, Implicit Grant, or hybrid flow, developers can request audiences at the /oauth2/auth endpoint using the audience query parameter:

https://{project.slug}.projects.oryapis.com/oauth2/auth
?client_id=...
&scope=...
&audience=https://api.my-cloud.com/user+https://some-tenant.my-cloud.com/

The audience query parameter can contain multiple strings separated by a URL-encoded space (+ or %20). The audience values must also be URL-encoded.

The values are validated against the allowed audiences defined in the OAuth 2.0 client. For instance, if an OAuth 2.0 client allows the audience https://api.my-cloud/user, it can request audience values like https://api.my-cloud/user or https://api.my-cloud/user/1234, but not https://api.my-cloud/not-user or https://something-else/.

The requested audience from the query parameter is then part of the login and consent request payload as the field requested_access_token_audience. Developers can then alter the audience using grant_audience.access_token when accepting the consent request. For example:


import { Configuration, OAuth2Api } from "@ory/client"

const ory = new OAuth2Api(
new Configuration({
basePath: `https://${process.env.ORY_PROJECT_SLUG}.projects.oryapis.com`,
accessToken: process.env.ORY_API_KEY,
}),
)

export async function acceptConsent(consentChallenge: string) {
const { data } = await ory.getOAuth2ConsentRequest({ consentChallenge })

return await ory
.acceptOAuth2ConsentRequest({
consentChallenge: consentChallenge,
acceptOAuth2ConsentRequest: {
// You may optionally ask the user to consent to the audience parameters too, but
// here we simply accept the requested token audience:
grant_access_token_audience: data.requested_access_token_audience,
},
})
.then(({ data }) => data)
}

When introspecting the OAuth 2.0 Access Token, the response payload includes the audience:


import { Configuration, OAuth2Api } from "@ory/client"

const ory = new OAuth2Api(
new Configuration({
basePath: `https://${process.env.ORY_PROJECT_SLUG}.projects.oryapis.com`,
accessToken: process.env.ORY_API_KEY,
}),
)

export async function introspectToken(accessToken: string) {
const { data } = await ory.introspectOAuth2Token({ token: accessToken })
console.log(data.aud)
}

Audiences in Client Credentials Grant

When performing the Client Credentials Grant, the audience parameter from the POST body of the /oauth2/token request is decoded and validated according to the rules described in the previous section, excluding login and consent, which are not a part of this flow.