Reputation: 1579
The context
I have a serverless web app built with AWS trio: API Gateway + Lambda + DynamoDB. The first page of the app send 2 http requests to get data and combine reponses to print the result.
/ APIGateway /projects => Lambda (DynamoDB request) \
web app => { } => display data
\ APIGateway /organizations => Lambda (Github API request) /
The problem
Every goes fine the first time I ask for the page. But if I try to refresh this page, I get a 403
error on /organizations
request. From there, if I wait ~3-5 minutes and I refresh the page again I correctly see all the data and my page is perfectly displayed. Sometimes, the GET /organizations
fails, sometimes, it's the GET /projects
.
Why I have to wait to be able to correctly refresh the page ? How can I fix it ?
Additional informations
When I have this 403
error, ...
200 OK
response to the OPTIONS /organizations
requestGET /organizations
request at all in the cloudwatch log (the OPTIONS
request is there, but not the GET
)Response headers are:
Connection:keep-alive
Content-Length:60
Content-Type:application/json
Date:Mon, 12 Dec 2016 11:31:29 GMT
Via:1.1 af2dd53407c5eae7ddf5c44e27a5dd1b.cloudfront.net (CloudFront)
X-Amz-Cf-Id:Kl1JS1ZCCJuGAmydXv3qDoq3E-rFZrlZbs8Bgvw8RSrb8xsjEyAJNQ==
x-amzn-ErrorType:AccessDeniedException
x-amzn-RequestId:8689b86c-c05e-11e6-b851-7ff70d9a3125
X-Cache:Error from cloudfront
(I dont know why I have x-amzn-ErrorType:AccessDeniedException
and X-Cache:Error from cloudfront
)
I have a CORS error in my chrome console :
XMLHttpRequest cannot load https://********.execute-api.eu-central-1.amazonaws.com/prod/organizations. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 403.
(... even if CORS is enabled and Access-Control-Allow-Origin:*
is present in the OPTIONS
response headers)
Thanks for your help!
Upvotes: 18
Views: 41686
Reputation: 1579
The origin of this issue was the custom authorizer which was generating a custom policy for a specific resource. As this policy was cached, when the second request arrives, it doesn't match with the one previously generated and returns an error.
In the Result TTL in seconds, type 0 and click Update. Now, you have to deploy your API to publish your changes :
def generatePolicy(principalId, context):
return {
'principalId': principalId,
'policyDocument': {
'Version': '2012-10-17',
'Statement': [{
'Action': 'execute-api:Invoke',
'Effect': 'Allow',
'Resource': 'arn:aws:execute-api:eu-central-1:123456789012:abcdefghij/prod/*'
}]
},
'context': context
}
You can be more precise in the Resource property with an array:
'Resource': [
'arn:aws:execute-api:eu-central-1:123456789012:abcdefghij/prod/GET/projects',
'arn:aws:execute-api:eu-central-1:123456789012:abcdefghij/prod/GET/user',
...
]
You can either Allow a superset of ressources and Deny specific ones.
Have a look on @Jeremiah 's link : https://forums.aws.amazon.com/thread.jspa?threadID=225934&tstart=0
Upvotes: 22