API Gateway CORS: no 'Access-Control-Allow-Origin' header

159,128

Solution 1

I get the same problem. I have used 10hrs to findout.

https://serverless.com/framework/docs/providers/aws/events/apigateway/

// handler.js

'use strict';

module.exports.hello = function(event, context, callback) {

const response = {
  statusCode: 200,
  headers: {
    "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
    "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS 
  },
  body: JSON.stringify({ "message": "Hello World!" })
};

callback(null, response);
};

Solution 2

If anyone else is running into this still - I was able to track down the root cause in my application.

If you are running API-Gateway with custom Authorizers - API-Gateway will send a 401 or 403 back before it actually hits your server. By default - API-Gateway is NOT configured for CORS when returning 4xx from a custom authorizer.

Also - if you happen to be getting a status code of 0 or 1 from a request running through API Gateway, this is probably your issue.

To fix - in the API Gateway configuration - go to "Gateway Responses", expand "Default 4XX" and add a CORS configuration header there. i.e.

Access-Control-Allow-Origin: '*'

Make sure to re-deploy your gateway - and voila!

Solution 3

If you have tried everything regarding this issue to no avail, you'll end up where I did. It turns out, Amazon's existing CORS setup directions work just fine... just make sure you remember to redeploy! The CORS editing wizard, even with all its nice little green checkmarks, does not make live updates to your API. Perhaps obvious, but it stumped me for half a day.

enter image description here

Solution 4

1) I needed to do the same as @riseres and some other changes.This are my response headers:

headers: {
            'Access-Control-Allow-Origin' : '*',
            'Access-Control-Allow-Headers':'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
            'Access-Control-Allow-Credentials' : true,
            'Content-Type': 'application/json'
        }

2) And

According to this documentation:

http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

When you use proxy for lambda functions on API Gateway config, the post or get methods have no added headers, only the options does. You must do it manually in the response(server or lambda response).

3) And

Beside that, I needed to disable the 'API Key Required' option in my API gateway post method.

Solution 5

Got my sample working: I just inserted 'Access-Control-Allow-Origin': '*', inside headers:{} in the generated nodejs Lambda function. I made no changes to the Lambda-generated API layer.

Here's my NodeJS:

'use strict';
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = ( event, context, callback ) => {
    const done = ( err, res ) => callback( null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers:{ 'Access-Control-Allow-Origin' : '*' },
    });
    switch( event.httpMethod ) {
        ...
    }
};

Here's my AJAX call

$.ajax({
    url: 'https://x.execute-api.x-x-x.amazonaws.com/prod/fnXx?TableName=x',
    type: 'GET',
    beforeSend: function(){ $( '#loader' ).show();},
    success: function( res ) { alert( JSON.stringify(res) ); },
    error:function(e){ alert('Lambda returned error\n\n' + e.responseText); },
    complete:function(){ $('#loader').hide(); }
});
Share:
159,128
Tyler
Author by

Tyler

Updated on July 08, 2022

Comments

  • Tyler
    Tyler almost 2 years

    Although CORS has been set up through API Gateway and the Access-Control-Allow-Origin header is set, I still receive the following error when attempting to call the API from AJAX within Chrome:

    XMLHttpRequest cannot load http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403.

    I attempted to GET the URL through Postman and it shows the above header is successfully passed:

    Passed headers

    And from the OPTIONS reponse:

    Response headers

    How can I call my API from the browser without reverting to JSON-P?

    • iSkore
      iSkore about 8 years
      Do you have it set up on the S3? If so, could you put up the Bucket Policy? Make sure you have the method in your policy
    • Tyler
      Tyler about 8 years
      No @iSkore it is set up on another server for testing. I also have tried it while accessing the file locally from my PC and through other servers. Is there something I need to configure on the page hosting server to allow use of CORS? My understanding is that only the API server needs settings altered for CORS.
    • iSkore
      iSkore about 8 years
      So have you added a CORS policy to your API though? And what do you mean 'page hosting server'? Just a regular server or a static server
    • Tyler
      Tyler about 8 years
      Yes, through the "Enable CORS" options in AWS API Gateway
    • iSkore
      iSkore about 8 years
      Gotcha, and did you include a policy with that?
    • iSkore
      iSkore about 8 years
      This may or may not help but found this link: stackoverflow.com/questions/10636611/…
    • RyanG
      RyanG about 8 years
      Does the OPTIONS call succeed? Can you post the results of the OPTIONS call? This is the result you would see if the OPTIONS call fails due to auth or other errors
    • Tyler
      Tyler about 8 years
      I added the OPTIONS result to the question
    • iSkore
      iSkore about 8 years
      So what exactly are you trying to do? GET data or find out what connection OPTIONS are available. Also if you are using CloudFront, sometimes it takes a while for them to deliver your files to the CDN. This only applies if you set up the CloudFront in the last hour or two.
    • iSkore
      iSkore about 8 years
      Hey check this on out too. This guy is using AJAX too. stackoverflow.com/questions/20035101/…
    • jackko
      jackko about 8 years
      API Gateway team here... If you use the 'Enable CORS' feature in the console, the configuration should be correct. My best guess would be that you aren't invoking the correct resource path in your API in the JavaScript that the browser is executing. If you attempt to make an API call to a non-existent method/resource/stage you'll receive a generic 403 with none of the CORS headers. I don't see how the browser could miss the Access-Control-Allow-Origin header if you're calling the right resource since the OPTIONS call in Postman clearly contains all the right CORS headers.
    • Tyler
      Tyler about 8 years
      @JackKohn I verified that the resource path is correct and was able to successfully access the method directly via the URL in Chrome. Also, the error explicitly mentions the lack of the 'Access-Control-Allow-Origin' header.
    • RyanG
      RyanG about 8 years
      Most times this misleading error message is due to the GET failing with a 404 or a 403 error. In those cases the CORS headers aren't returned by the service. Is the client signing the request with credentials and is the IAM policy for those credentials authorized to call that API/method? Can you confirm that the URL used by the client is correct?
    • Tyler
      Tyler about 8 years
      @RyanG-AWS the client is not signing the request because the API is authenticated by the resource it calls using a user-specific token, so the credentials are not a factor. I can call the API by visiting the URL directly in the browser and I get the appropriate response.
    • Nirmal
      Nirmal about 8 years
      @makinbacon: Did you find a solution for this? I'm going through the same issue here.
    • Tyler
      Tyler about 8 years
      @Nirmal I think I removed the API and re-added it, then enabled CORS and it worked for me. I am still not sure exactly what changed causing it to work.
    • Nirmal
      Nirmal about 8 years
      @makinbacon: Ah, I just tried that, and it works for some strange reasons. I have hundreds of resources and methods and it's going to be one hell of a task to recreate all of them. This can also be achieved by manually specifying the header in the Integration Response. Either way, it's a lot of work. Thanks for the help.
    • scald
      scald almost 8 years
      My methods and stage were generated automatically by Lambda. I enabled CORS after the fact. Same errors as OP. I blew away the auto generated stuff, created a new API and methods, deployed to a new stage, and it worked fine.
    • Stephen Tetreault
      Stephen Tetreault over 7 years
      just tried this, with no luck :(
    • Michael Tung
      Michael Tung over 7 years
      See my answer here it could be related to API key issue, stackoverflow.com/questions/34325009/…
    • Kevin B
      Kevin B about 7 years
      We need to see the headers in the response from the actual ajax request that is throwing said error. Postman results aren't really all that useful. The error states that said header doesn't exist, i'm more inclined to believe that it doesn't exist than an error is being thrown stating that something doesn't exist when it actually does.
    • Kevin B
      Kevin B about 7 years
      The response had HTTP status code 403 specifically hints that you're receiving an error response, and the error response likely does not have said cors header.
    • Kent V
      Kent V almost 6 years
      My solution was delete API Gateway and Create a new one, enble cors. Thanks!!!
    • user763648
      user763648 almost 4 years
      Deleting and recreating the resource did not help me. I have a resource with GET and OPTIONS and only the OPTIONS gets the headers even though in the CORS screen both methods are checked.
  • MannyC
    MannyC almost 7 years
    I've found a lot of Amazon's documentation to be out-of-date, even with the "../latest/.." path fragment. After scrapping everthing about a week ago, the CORS button suddenly stated working properly. The API created the "ANY" method automatically and the CORS button created the "OPTIONS" method automatically - I added nothing to the API. The "GET" above works and I've since added an ajax "POST" which also works without me touching the API.
  • Admin
    Admin about 6 years
    Yep, I think the subtle thing a lot of us miss initially is that once you configure your API Gateway integration for the Lambda function with "Use Lambda Proxy Integration", then you must do as you and others are stating and ensure the headers are added programmatically in your lambda's response. The auto-gen stuff that is created by "Enabling CORS" on an API Gateway and it creating an OPTIONS responder is great but doesn't get you all the way there if you set "Use Lambda Proxy integration" in the Integration Request within API Gateway.
  • Gabriel Doty
    Gabriel Doty almost 6 years
    @efong5 glad it helped someone!
  • Will
    Will almost 6 years
    For those wanting to do this with the AWS CLI, use: aws apigateway update-gateway-response --rest-api-id "XXXXXXXXX" --response-type "DEFAULT_4XX" --patch-operations op="add",path="/responseParameters/gatewayresponse.header.Ac‌​cess-Control-Allow-O‌​rigin",value='"'"'*'‌​"'"'
  • Eric Brown
    Eric Brown over 5 years
    Fixed the problem I was having as well. Thank you for your answer!
  • Costa Michailidis
    Costa Michailidis over 5 years
    I don't use serverless, but this solved my problem. Guess you need to pass those headers out from the actual source.
  • Kevin
    Kevin over 5 years
    FYI, there's an issue with the example presented here. If you have "Access-Control-Allow-Credentials": true, you can't have the wildcard * for Access-Control-Allow-Origin. This rule is enforced by the browser. See here and here
  • Force Hero
    Force Hero over 5 years
    I'm not using custom Authorizers and still needed this as my request had bad JSON in it - thank you!
  • danieln
    danieln over 5 years
    note to myself - don't forget to deploy the API afterwards :)
  • mitesh7172
    mitesh7172 over 5 years
    This is not working, Again shows same error Request header field access-control-allow-credentials is not allowed by Access-Control-Allow-Headers in preflight response.
  • Snedden27
    Snedden27 about 5 years
    how can you do this with java RequestHandler<RequestClass, ResponseClass> class?
  • Leonid Usov
    Leonid Usov about 5 years
    For anyone curious, here is the official docs mentioning this: docs.aws.amazon.com/apigateway/latest/developerguide/… > For Lambda or HTTP proxy integrations, you can still set up the required > OPTIONS response headers in API Gateway. However, you must rely on the > back end to return the Access-Control-Allow-Origin headers because the > integration response is disabled for the proxy integration.
  • Shn
    Shn about 5 years
    I spent almost two hours trying to figure out how to get Access-Control-Allow-Origin added to the method response using the AWS console, but this was also the only thing that worked for me.
  • Priyanka V
    Priyanka V about 5 years
    setting only "Access-Control-Allow-Origin" : "*" from lambda solved the issue
  • Robin C Samuel
    Robin C Samuel almost 5 years
    and re-deploy! :)
  • Michael
    Michael almost 5 years
    Strange, this worked for me, but I didn't have to redeploy. I did try redeploying earlier. Not sure why it worked for me.
  • DeepFreez
    DeepFreez over 4 years
    Adding the CORS header to 4XX allows you to see the actual error message instead of the CORS error.
  • Chris Christensen
    Chris Christensen over 4 years
    This was it. Literally working on this for two days. Not sure the logic in not at least prompting for a redeploy after you edit the gateway.
  • lase
    lase over 4 years
    @ChrisChristensen glad you got it figured out - there's always something so relieving yet incredibly defeating about problems like this
  • CamHart
    CamHart over 4 years
    Man am I glad I left this comment. This keeps happening to me :D.
  • Dinesh Kumar
    Dinesh Kumar over 4 years
    Why is this answer down-voted but there are other similar answers below?
  • BennyHilarious
    BennyHilarious over 4 years
    This worked for me...after reading the manual properly : Important When applying the above instructions to the ANY method in a proxy integration, any applicable CORS headers will not be set. Instead, your backend must return the applicable CORS headers, such as Access-Control-Allow-Origin. docs.aws.amazon.com/apigateway/latest/developerguide/…
  • Zac Grierson
    Zac Grierson over 4 years
    I love finding my own solution to a future reoccurring issue.
  • Guillaume Raymond
    Guillaume Raymond over 4 years
    Thanks for your contribution however can you explain why it did workin for you? I invite you to read this guide to improve your answer : "How I write a good answer" here: stackoverflow.com/help/how-to-answer
  • ewalel
    ewalel about 4 years
    For AWS based API gateway invoking, this solution works
  • James Shapiro
    James Shapiro about 4 years
    Just FYI, the way to do this from the AWS console is to click on the method (i.e. "POST" then "enable CORS" then check off the 4XX options, then deploy.
  • Rahul Khanna
    Rahul Khanna almost 4 years
    This is the answer that is valid in 2020. Thanks
  • Shlomi Bazel
    Shlomi Bazel almost 4 years
    Thank you for that. Didn't notice the "Enable CORS" in the resource. Made me lose my mind.
  • Surjith S M
    Surjith S M almost 4 years
    RE-DEPLOY RE-DPLOY RE-DEPLOY
  • Nick H
    Nick H over 3 years
    Where do you find this menu? I don't see it anywhere.
  • Jason
    Jason over 3 years
    @NickH take a look at the picture from Ravi Ram. Under "Actions", there should be an item called "Enable CORS" and when you select that, the menu will show up.
  • thenewpotato
    thenewpotato almost 3 years
    Just tried this but got this error in the browser: "Response to preflight request doesn't pass access control check: It does not have HTTP ok status." Any ideas? I know I can set the status code for all 4XX requests (say, to 200), but that doesn't sound like terribly good practice
  • Alisha Raju
    Alisha Raju almost 3 years
    Just after seeing this comment, I checked my URL. AHH! and it was indeed an issue with my URL. There was an additional '/' param added due to which I was getting CORS error. This comment literally saved me! Thanks a ton for pointing this out!!
  • StayCool
    StayCool over 2 years
    I can't find this menu anywhere. I suspect many of these solutions are for REST api, not HTTP api.
  • jcollum
    jcollum over 2 years
    @riseres if Access-Control-Allow-Credentials has to be domain specific as @Kevin said, you should edit the answer to clarify that because a lot of people aren't going to read the comments to check that
  • Michael
    Michael over 2 years
    This comment saved my day! I didn't know I had to "Deploy API" every time I changed the "Enable CORS"
  • dataviews
    dataviews over 2 years
    I've faced this error too. It's important to enable logging at your lambda level (if you're using a proxy [API gateway -> lambda] for example) as well as at api gateway to understand where the issue is happening. In my case, I did not have 4xx or 5xx enabled for CORS and i had to check lambda cloudwatch logs to understand where the error was happening.
  • Neil
    Neil about 2 years
    I suffered this issue in 2022 and spent hours trying to fix / troubleshoot - MAKE SURE YOU USE SINGLE QUOTES!
  • Scott Jodoin
    Scott Jodoin about 2 years
    When setting up the Lambda there is some information text: Cross-origin resource sharing (CORS) CORS is required to call your API from a webpage that isn’t hosted on the same domain. To enable CORS for a REST API, set the Access-Control-Allow-Origin header in the response object that you return from your function code.
  • owais
    owais about 2 years
    Made this mistake second time. It was very frustrating.
  • Ion Scorobogaci
    Ion Scorobogaci about 2 years
    if you wish to do it through cdk, then this is how you do it : docs.aws.amazon.com/cdk/api/v1/docs/…