Chris Rice
Chris Rice

Reputation: 819

AWS Cognito JWT will not pass validation with .net core api, missing cognito configuration?

I am trying to attach an angular application to a .NET core API utilizing the JWT token. At this point i have the local angular app authenticating with Cognito and getting the user account.

I've followed this to get the token attached to the request. https://medium.com/@umashankar.itn/aws-cognito-hosted-ui-with-angular-and-asp-net-core-5ddf351680a5

 Amplify.Configure({
    Auth: {
      region: 'us-west-2',
      userPoolId: 'us-west-MY POOL',
      userPoolWebClientId: 'MY APP CLIENT ID'
    }
  }
});
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    if (request.url.indexOf(environment.api.baseUrl) == 0) {
      return this.getToken().pipe(mergeMap(token => {
        request = request.clone({
          setHeaders: {
            Authorization: `Bearer ${token}`
          }
        });
        return next.handle(request);
      }));
    }
    return next.handle(request);
  }
}
getToken() {
    return from(
      new Promise((resolve, reject) => {
        Auth.currentSession()
          .then((session) => {
            if (!session.isValid()) {
              resolve(null);
            } else {
              resolve(session.getIdToken().getJwtToken());
            }
          })
          .catch(err => {
            return resolve(null)
          });
      })
    );
  }

And i can confirm that it is adding the token to the request.

enter image description here

Interesting thing to note is that i'm using the session.getIdToken().getJwtToken() but there also is session.getAccessToken().getJwtToken() and they are different. I can't find anything telling me what the difference is, but i've tried both and they both have the same issue.

For the server side i've followed this answer to setup the .net core site and i can confirm that it is appropriately downloading the keys from /.well-known/jwks.json. It however just keeps rejecting the request with authentication failure.

How to validate AWS Cognito JWT in .NET Core Web API using .AddJwtBearer()

 services
    .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.SaveToken = true;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
            {
                // get JsonWebKeySet from AWS
                var json = new WebClient().DownloadString(parameters.ValidIssuer + "/.well-known/jwks.json");
                // serialize the result
                return JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
            },
            ValidateIssuer = true,
            ValidIssuer = $"https://cognito-idp.us-west-2.amazonaws.com/us-west-MYID",
            ValidateLifetime = true,
            LifetimeValidator = (before, expires, token, param) => expires > DateTime.UtcNow,
            ValidateAudience = true,
            ValidAudience = "MY APP CLIENT ID"
        };
    });
app.UseAuthentication();
[HttpGet]
[Authorize]
public IEnumerable<Device> Get()
{
   return 'my devices...';
}

The angular app is running at http://localhost:4200 and the .net core is running at https://localhost:44300.

So the question i have is, am i missing some sort of setup in my cognito app client? What am i missing to get the .NET core app to take the JWT?

enter image description here enter image description here

Upvotes: 1

Views: 1576

Answers (1)

Chris Rice
Chris Rice

Reputation: 819

Turns out i actually did have everything correct as far as Cognito goes.

What i did have was this.

app.UseRouting();

app.UseAuthorization();
app.UseAuthentication();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

Which is not the correct order for things to work... this is..

app.UseRouting();

app.UseAuthentication(); <-- Authentication before authorization
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

Upvotes: 4

Related Questions