AWS API Method fails with 504 Error; Using Cognito and CORS

Ryan Gibbs

Summary:

I'll get into the weeds below, but essentially the end goal I'm aiming for is to retrieve a value from a AWS Lambda function and return it to the client side of my page. The page is using AWS Cognito to authenticate a user and once authenticated it posts to an API Gateway endpoint to retrieve data back from my Lambda function (The Lambda queries DynamoDB). This is the part I'm struggling with because I get a 504 (Timeout) error back.

I know my Lambda returns values correctly and that my API, theoretically, is implemented correctly, or at least that it works from the test section of the API Gateway Management Console.

Details:

I've spent quite a bit of time trying to figure out exactly where my error lies, and I believe it has something to do with the Cognito authentication or CORS. If I remove the authorization requirement from my API gateway method and don't send the authorization token, then I get the expected response back from the post. This leads me to believe that maybe the root of my issue is incorrectly implementing Cognito authorization on the Post method.

I'm using CORS because the site is hosted on an EC2, but is using AWS API Gateway for its RESTful routes.

Also, I use the Cognito javascript SDK to authenticate the user, then pass the authToken into the custom headers in my ajax.

Here's my ajax:

$.ajax({
    method: 'POST',
    url: _config.api.invokeUrl + '/getusersites',
    dataType: "json",
    crossDomain: true,
    cors: true,            
    xhrFields: {
        withCredentials: true
    },
    headers: {
        Authorization: token
    },            
    data: JSON.stringify(user),
    success: completeRequest,            
    error: ajaxError  
});

Now unless I'm misunderstanding, when I look at the headers in the Network tab of Chrome's DevTools, it appears that the post is failing on the preflight. Because when I look at that General section of that URL, it says:

Request Method: OPTIONS

Status Code: 504

(See update below for full headers)

And the body is:

{"message": "Endpoint request timed out"}

So that would lead me to believe that the Option request for CORS is timing out prior to the Post even being called.

I'm also getting the console error:

Failed to load (My API endpoint here): Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '(My origin domain)' is therefore not allowed access. The response had HTTP status code 504.

So to me that looks like the CORS preflight is failing to respond before the API times out.

I do not have Authorization enabled in the method execution for the Options method on my API resource, but I do have it enabled for the Post method. As I said previously, if I disable that then everything works as expected, only there's no Cognito authorization check.

So what am I doing wrong here? Is it a CORS issue? Auth issue? Both?

What I've tried:

I attempted to add the CORS headers to the Integration Response of my Post method. However, I believe this didn't make a difference because they would only be returned with a 200 (Success) code, and I'm getting the 504 code.

I thought perhaps there was a permissions issue with either my Lambda function or in my Cognito User Pool's authorizer. So I went into IAM and gave them both all the permissions they could possibly want. This didn't change the result.

I was working under the theory my ajax might be incorrectly set up, so I've tried a few different ways of implementing the parameters of the post, however the only one that works is if I disable authorization and don't send the custom header with the auth token.

I ensured that my API resources have CORS enabled and have been redeployed. If only it had been that simple.

I've googled enough to overheat a few google servers, but I'm out of ways to ask this question.

Final Thoughts:

If you've taken the time to read my novel, I appreciate it. If anyone has tried to do something similar or has any ideas of directions I could go next with this issue. I'm still learning how to handle all this AWS implementation, so I'm sure I've just made some silly mistake somewhere.

Thank you in advance for your replies.

>>>UPDATE:<<<

Per request, here are the full headers for the OPTION attempt. There is no POST because of the 504 error on the OPTION attempt.

General:

Request URL: https://(API endpoint).amazonaws.com/prod/getusersites

Request Method: OPTIONS

Status Code: 504

Remote Address: 52.84.11.37:443

Referrer Policy: no-referrer-when-downgrade

Response Headers:

content-length: 41

content-type: application/json

date: Wed, 04 Apr 2018 16:16:14 GMT

status: 504

via: 1.1 0a9f4502819b08c3a7919c963887be2b.cloudfront.net (CloudFront)

x-amz-apigw-id: E0wHvE3doAMFgrA=

x-amz-cf-id: pVgd6gNNtw-cYxKe4s9jdEnfU2rBle8cd9MyP34aduYi0_ds4YBRCA==

x-amzn-requestid: 6e014d82-3823-11e8-bc41-3f13ca287d3c

x-cache: Error from cloudfront

Request Header:

:authority: (API Endpoint)

:method: OPTIONS

:path: /prod/getusersites

:scheme: https

accept: /

accept-encoding: gzip, deflate, br

accept-language: en-US,en;q=0.9

access-control-request-headers: authorization

access-control-request-method: POST

cache-control: no-cache

origin: https://(Origin Domain)

pragma: no-cache

user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36

Ryan Gibbs

It's taken forever, but I finally figured out what was wrong.

The problem was how AWS set up the OPTIONS Integration Request when I implemented CORS through the AWS API Gateway Console.

By default, it sets up the Integration Request as HTTP, using the API invocation URL as the endpoint. For some reason, this was causing the OPTIONS preflight to time out and respond with 504. Still don't know why, likely had to do with the authentication.

Solution:

In the Integration Request section of my OPTIONS method I changed the Integration type from HTTP to MOCK.

Then, after saving that, I had to go to the Integration Response section of my OPTIONS method, expand the 200 HTTP status code, expand the Headers Mappings and reenter the values for my headers. The headers were still there, but the values had been removed. My final response headers looked like this:

Access-Control-Allow-Headers 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'

Access-Control-Allow-Origin 'https://MyDomain.com'

Access-Control-Allow-Credentials 'true'

Access-Control-Allow-Methods 'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'

After setting those, I redeployed the API and It worked perfectly! Now I'm off to drink a bottle off champagne. :)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

CORS access error for PUT method, api on aws hosted on elastic beanstalk

CORS issue during AWS Cognito Hosted UI sign in using Google

AWS API gateway authentication without using Cognito

AWS Cognito and Websocket Api using Lambda Authorizer

504 error with post API

AWS Amplify API Gateway cors error after using authorizer: aws_iam

Download file from AWS S3 using fetch method throws CORS error

AWS API Gateway CORS pre-flight check fails

How to fix the cors origin error on Jquery when POST method fails?

AWS API Gateway error, Network error communicating with endpoint, 504 Gateway Timeout

Using AWS Cognito Vuejs

AWS API Gateway - using Access Token with Cognito User Pool authorizer?

AWS API gateway for K8s using Cognito with JWT

Authenticating a REST API with Cognito using AWS Amplify & Android

Security token is invalid when calling API using AWS Amplify & Cognito

Error while doing IdP initiated login using AWS Cognito

type error for fetch while using aws-cognito-identity-js

How to avoid the CORS error from an API created in AWS API Gateway?

How do I avoid CORS problem when using OpenID Connect (AWS Cognito)?

api gateway error 401 when using cognito to authenticate API

Trigger an AWS Alarm when an API Gateway invocation hits its 29 second timeout and returns a 504 error

AWS - Error 504 - Gateway timeout - Flask Application

AWS Api Gateway 403 error - CORS enabled from all origins

XMLHttpRequest error in flutter web [Enabling CORS AWS API gateway]

Getting CORS error when calling AWS API from Jquery

Why is AWS Lambda, API Gateway returning a CORS error

Integrating AWS Cognito with API for authentication

AWS Cognito Unknown Error on signin

How to configure CORS for AWS API Gateway using OpenAPI?