Restricting access tokens to an audience
An access token that contains an audience (aud) claim names the resource servers that are allowed to accept it. A resource server must verify that its own identifier is contained in the aud claim and reject the token if it is not.
Use the audience claim to make sure that an access token issued for one API cannot be replayed against a different, more sensitive API. This attack is known as the confused deputy problem.
nevisAuth builds the audience claim from the resource request parameter and from the resource servers that you configure in nevisMeta, in accordance with RFC 8707 and RFC 9068.
The audience claim is available as of nevisAuth 9.2605.0.16.
The following diagram shows what the audience claim prevents. The client receives a token for the orders API and sends it to the payments API.
nevisAuth adds the aud claim to the access token. Enforcing the claim is the task of the resource server: each resource server must compare the aud value of an incoming token with its own identifier and reject the token if the values do not match. nevisAuth does not reject the call to the payments API on behalf of that API.
Preconditions for the audience claim
- nevisMeta is set up, see Setting up a nevisMeta Instance.
- An OAuth 2.0 Authorization Server is set up, see Setting up an OAuth 2.0 Authorization Server.
- nevisMeta is the data source of the authorization server. The audience claim is not available with other data sources.
- Every resource server that you want to use as an audience has a value in the URL field in nevisMeta. RFC 8707 requires an absolute URI, and a resource server without a URL value can never become an audience. For more information on the resource server entity, see Entities.
Configuring the audience claim
To add the audience claim to the issued access tokens, perform the following steps:
- In the nevisMeta Web Console, open each resource server that you want to use as an audience, and set URL to the absolute URI of the API, for example
https://api.example.com/orders. - In nevisAdmin 4, open the OAuth 2.0 Authorization Server / OpenID Provider pattern.
- On the Token tab, set Audience Field Strategy to
resource. - Deploy the configuration.
For the field description, see Audience Field Strategy in the patterns reference.
If you configure the authorization server without nevisAdmin 4 patterns, set the property oauth2.audienceField.strategy to resource on the AuthorizationServer AuthState, see AuthorizationServer.
The default value is disabled. When you change the value to resource, nevisAuth rejects every authorization request that contains neither a resource parameter nor scopes of exactly one resource server that has a URL value. Verify the requests of all clients before you enable the strategy in a production setup.
How nevisAuth determines the audience
nevisAuth determines the audience at the authorization endpoint. There are two paths: the client names the resource explicitly, or nevisAuth derives the resource from the requested scopes.
Audience from the resource parameter
Send the resource parameter on the request to the authorization endpoint. To name a resource server, send its URL value. Such a value must meet the following conditions:
- The value is an absolute URI.
- The value does not contain a fragment.
- The value matches the URL value of a resource server in nevisMeta.
nevisAuth compares the value with the URL values as an exact string comparison. For this reason, https://api.example.com/orders and https://api.example.com/orders/ are two different values, and only the configured one is accepted.
To request several audiences, send the resource parameter one time for each value. Do not send several values as one space-separated list.
GET /oauth2/authorize?response_type=code
&client_id=example-client
&scope=orders:read payments:read
&resource=https://api.example.com/orders
&resource=https://api.example.com/payments
The aud claim of the issued access token then contains both values.
Audience from the requested scopes
If the request contains no resource parameter, nevisAuth derives the audience from the requested scopes. nevisAuth matches the requested scopes against the scopes of the resource servers in nevisMeta. Exactly one resource server must match, and that resource server must have a URL value. The aud claim then contains that URL value.
nevisAuth excludes the standard OpenID Connect scopes from this match, because these scopes belong to no single resource server:
openidprofileemailaddressphoneoffline_access
As a result, a request that contains only standard OpenID Connect scopes has no scope left to derive a resource server from, and nevisAuth rejects it. When the resource strategy is active, such requests must contain a resource parameter.
The following table shows the outcome for each combination of the resource parameter and the requested scopes.
resource parameter | Requested scopes | Outcome |
|---|---|---|
| One or more values, all known | Any | Access token with the resource values as audience |
| One or more values, one unknown | Any | Error invalid_target |
| None | Scopes of exactly one resource server that has a URL value | Access token with that URL value as audience |
| None | Scopes of exactly one resource server that has no URL value | Error invalid_scope |
| None | Scopes of several resource servers | Error invalid_scope |
| None | Only standard OpenID Connect scopes | Error invalid_scope |
Scopes are not restricted to the audience
The audience claim restricts which resource servers can accept the access token. It does not restrict the scopes in the access token.
An access token contains every scope that the client is authorized to request and that the request asks for, independently of which resource server owns each scope. A request that names one resource in the resource parameter and asks for scopes of three resource servers produces an access token with the scopes of all three.
Take this into account when you plan the scopes of your resource servers.
Audience of refreshed access tokens
An access token that a client obtains with a refresh token keeps the audience of the original access token. The client cannot change the audience through the refresh, and a resource parameter on the refresh request has no effect.
Flows that support the audience claim
nevisAuth adds the audience claim in the Authorization Code, Implicit, and Hybrid flows.
The Client Credentials flow and the JWT Bearer flow do not add an audience claim to the access token.
Troubleshooting the audience claim
The OAuth 2.0 error codes that nevisAuth returns to the client are the ones the standards define, and several conditions share one code. To find the cause, read the nevisAuth log. The following table maps each condition to the log message that identifies it.
| Error returned to the client | Condition | nevisAuth log message |
|---|---|---|
invalid_target | A resource value is not an absolute URI, contains a fragment, or matches no resource server | Invalid or unknown resource parameter: '...' |
invalid_scope | The requested scopes match at least one resource server that has no URL value | Requested scopes [...] map to at least one resource without URL. |
invalid_scope | The requested scopes match no resource server | Requested scopes [...] do not map to any resource server. |
invalid_scope | The requested scopes match several resource servers that all have a URL value | Requested scopes [...] map to multiple resource servers, which is not allowed without an explicit resource parameter. |
nevisAuth verifies the three scope conditions in the order of the table. If the requested scopes match several resource servers and one of them has no URL value, the log contains the message about the missing URL, not the message about the several resource servers.
If the access token contains no aud claim at all, verify the following:
- Audience Field Strategy is set to
resource, and the configuration is deployed. - The flow is Authorization Code, Implicit, or Hybrid.
- The
resourceparameter is sent to the authorization endpoint. The token endpoint ignores it.