I followed this guide to build an API using Lambda and API Gateway and encountered some problems along the way, but finally managed to fix the problems (thanks to Firefox’s network error logs).
Maybe the guide is already covering this and I simply missed it when I was reading it. I wanted to share my journey here in case others might find it helpful.
I created a Lambda function, an Auth0 Custom Authorizer function, and put it behind API Gateway to expose the Lambda function to the HTTP world and securing it with the Custom Authorizer at the same time.
Everything seemed to be working just fine. I uploaded an HTML page to an S3 static website and I could login via Auth0 with no problem.
I could also obtain a JWT token:
curl --request POST \
--url https://xyz.auth0.com/oauth/token \
--header 'content-type: application/json' \
--data '{"client_id":"...","client_secret":"...","audience":"...","grant_type":"client_credentials"}'
and then go to the API Gateway console to test the custom authorizer and it was working like a charm:
However, when I later added some logic to the HTML page to actually invoke the API using jQuery, the OPTION
request succeeded but then I got this error message in Chrome:
Failed to load https://xyz.execute-api.xyz.amazonaws.com/xyz: Request header field
Access-Control-Allow-Credentials
is not allowed byAccess-Control-Allow-Headers
in preflight response.
Being a total CORS noob, this was not very helpful to me. I opened the website in Firefox and after reading the error message a couple of times, I I finally understood what it means:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xyz.execute-api.xyz.amazonaws.com/xyz. (Reason: missing token
‘access-control-allow-credentials’
in CORS header‘Access-Control-Allow-Headers’
from CORS preflight channel)
So what did it mean?
By default, when enabling CORS on API Gateway, it sets the value of the Access-Control-Allow-Headers
to Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
. As you can see, access-control-allow-credentials
is missing there.
I edited the value of the header on the OPTION
method and changed it to Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Access-Control-Allow-Credentials
and voila! The error message vanished and the requests succeeded.
Just for the sake of completeness, the following code snippet show how I was trying to invoke my API:
var settings = {
"async": true,
"crossDomain": true,
"url": "https://xyz.auth0.com/oauth/token",
"method": "POST",
"headers": {
"content-type": "application/json"
},
"data": "{\"client_id\":\"...\",\"client_secret\":\"...\",\"audience\":\"...\",\"grant_type\":\"client_credentials\"}"
}
$.ajax(settings).done(function (response) {
var payload = {
source: "lorem ipsum"
};
$.ajax({
type: "POST",
url: "https://my-api.execute-api.xyz.amazonaws.com/xyz";,
data: JSON.stringify(payload),
headers: {
"Authorization": `Bearer ${response.access_token}`
},
success: function (response) {
console.log(response);
}
});
});