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