27

When Amazon Cognito issues access tokens it doesn't include an aud field.

In the documentation for Cognito tokens, the aud field is listed for id tokens (always set to the same value as client_id), but not for access tokens.

The relevant section of the JWT specification says:

If the principal processing the claim does not identify itself with a value in the "aud" claim when this claim is present, then the JWT MUST be rejected.

So, what's going on here. Who's right? Is this a security concern?

I notice that the iss section of the token is specific to my user pool, and that can't have been tampered with, since it's signed by Amazon, so I think I should be safe

OAuth 2 and JWT are very confusing though, so I wanted to get more opinions.

Community
  • 1
  • 1
GlennS
  • 5,251
  • 6
  • 28
  • 31

4 Answers4

8

From my reading of the RFC I do not think that AWS is doing anything wrong, specifically (note my emphisis):

If the principal processing the claim does not identify itself with a value in the "aud" claim when this claim is present, then the JWT MUST be rejected.

Use of this claim is OPTIONAL.

Which, I believe, means that AWS is fine, because it's simply omitting the claim in the case of the access token, but it is identifying itself (in it's own way), by setting it to client_id when it does make the claim on the id token.

It should be noted that the access token itself does encode and enforce the audience; in that when you use it against AWS' APIs it will enforce that you only receive the resources available on the client_id/scope that it was issued for.

thomasmichaelwallace
  • 7,926
  • 1
  • 27
  • 33
  • 10
    Thanks for the response. I contacted AWS, discussed a few things including this with them and they've as a result submitted a feature request to the cognito development team to consider optionally allowing the inclusion of the 'aud' claim in access tokens, mimicking the likes of auth0 and okta. – Kyanite Aug 26 '19 at 17:57
  • 1
    @Kyanite do you have any more info on that feature request? – BeefCake Nov 04 '20 at 10:28
  • 3
    @Kyanite any news on the feature request? The absence of `audience` claim makes the API Gateway JWT Authorizer useless, since it requires a list of valid `audience` values. – Andre Albuquerque Aug 02 '21 at 21:58
  • 1
    For JWT authorizers, the documentation notes (now, if not then!) that the audience entries for the authorizer are used as follows: "aud or client_id – Must match one of the audience entries that is configured for the authorizer." See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html#http-api-jwt-authorizer.evaluation – Daniel Jan 22 '22 at 12:33
4

Many dotnet web application cognito tutorials are based on the wrong assumption that the client id will be the Audience Id in the following setup which will NOT WORK.

          services
          .AddAuthentication(options => {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options => 
            {
                options.Audience = "Client ID";
                options.Authority = "https://cognito-idp.ap-southeast-2.amazonaws.com/USERPOOLID";
                options.RequireHttpsMetadata = false;

            });

A temporary workaround is not to validate the audience:

services
            .AddAuthentication(options => {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(options => 
            {
                // AWS cognito jwt token does not have aud included so that we cannot validate audience.
                // options.Audience = "Client ID";
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false
                };
                options.Authority = "https://cognito-idp.ap-southeast-2.amazonaws.com/USERPOOLID";
                options.RequireHttpsMetadata = false;

            });
Yang Zhang
  • 4,540
  • 4
  • 37
  • 34
2

It looks like AWS Cognito now includes a client_id claim on the access tokens. I did not find it specified in any AWS documentation, the only thing I could find was this GitHub issue: https://github.com/ghdna/cognito-express/issues/11

Sp3ct3R
  • 715
  • 1
  • 12
  • 24
  • 1
    Yes, client_id claim is included, and for JWT authorizers, the documentation notes (now, if not then!) that the audience entries for the authorizer are used as follows: "aud or client_id – Must match one of the audience entries that is configured for the authorizer." See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html#http-api-jwt-authorizer.evaluation – Daniel Jan 22 '22 at 12:36
0

Typically, an aud claim is used to identify the recipients or principal such that the recipient can verify that the jwt is meant for it to validate.

However, aud is an optional claim. So, AWS keeps it optional.

Instead of tying who can process the jwt using the aud claim, AWS leaves it up to the recipient (e.g. aws api gw) to check for a client_id claim to identify if the jwt should be processed.

References:

https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3

human
  • 2,250
  • 20
  • 24