Amplify: CORS header ‘Access-Control-Allow-Origin’ missing error even though CORS is enabled in API Gateway and Lambda headers
Asked Answered
R

8

16

I'm using Amplify, and have my API Gateway proxying to Lambda. I've enabled CORS on my /{proxy+} and deployed the API. In my Lambda function, I'm setting the appropriate header in my trivial function:

import json


def handler(event, context):
    print("received event:")
    print(event)
    return {
        "statusCode": 200,
        "headers": {
            "Access-Control-Allow-Credentials": True,
            "Access-Control-Allow-Headers": "Content-Type",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET",
            "Access-Control-Allow-Origin": "*",
        },
        "body": json.dumps(event),
    }

This Lambda function sits behind an API Gateway resource which is authenticated via Cognito.

When I invoke my API using Amplify:

let myInit = {
          headers: {
            Authorization: `Bearer ${(await Auth.currentSession())
              .getIdToken()
              .getJwtToken()}`
          }
        }; 

API.get("adminapi", "/admin", myInit) ...

I get the dreaded CORS header 'Access-Control-Allow-Origin' missing from my GET request:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/admin. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

I see it returned in the OPTIONS request:

enter image description here

I even tested in Postman to verify the headers are coming back:

enter image description here

What am I doing wrong here? It doesn't look like the call is getting past API Gateway. I wonder if it has to do with authentication. When I test from Postman using my IAM credentials it works fine, but from my web app using the bearer token it fails as above.

Rodd answered 14/4, 2020 at 11:10 Comment(4)
Always quote the full error message. I suspect it says that the header is missing from the preflight response and not the requested resource.Dewittdewlap
Header is missing from the GET request. The OPTIONS request works just fine.Rodd
Updated question to include more details.Rodd
Did you ever found the solution for this ?Babbette
R
8

I've just struggled with something similar. The question here asks why the browser is returning a CORS errors when hitting API Gateway with Amplify despite CORS headers being configured correctly in the endpoint.

Aside from incorrect CORS header config, Amplify / API Gateway gives a CORS error if certain aspects of the request are incorrect. The ones I've comes across are:

  • The HTTP verb you are using does not exist against the endpoint
  • The endpoint you are using doesn't exist (e.g. a typo)
  • The Content-Type header is incorrect

The latter was causing me issues. It seems that Amplify.API.post and Amplify.API.put both send a Content-Type of application/x-www-form-urlencoded by default. My API was expecting application/json and the result was a CORS error.

Roush answered 21/7, 2021 at 23:15 Comment(0)
U
1

When using fetch() in js when I removed the Cognito Authentication from my API Gateway OPTIONS endpoints it worked. Chrome and Firefox don't send the Authorize headers to OPTIONS. Might be different with amplify though. Quoting: https://fetch.spec.whatwg.org/#http-responses ...

"For a CORS-preflight request, request’s credentials mode is always "same-origin", i.e., it excludes credentials, but for any subsequent CORS requests it might not be."
Uniparous answered 9/3, 2021 at 11:52 Comment(0)
H
0

I'd assume that you forgot to handle the OPTIONS verb that's used for the preflight request and return the header there.

You are sending an Authorization header, which is not in the list of allowed headers for "simple" requests, hence a preflighted request is done.

Furthermore, in order for credentials to get through, you have to ensure that the Access-Control-Allow-Credentials: true header is set as well.

It's not apparent from the code snippet what content type your request body is, but if it's anything other than application/x-www-form-urlencoded, multipart/form-data or text/plain (say, application/json), you also need to whitelist the Content-Type header using Access-Control-Allow-Headers: Content-Type.

Huberthuberto answered 14/4, 2020 at 11:13 Comment(2)
OPTIONS is being handled (somewhere) because it returns access-control-allow-origin: *. I updated my function to include "Access-Control-Allow-Credentials": True in the response headers. Same situation. Access-Control-Allow-Headers is set in API Gateway by default as 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'.Rodd
What happens if you put Fiddler in between? Check what actually goes over the line and how it differs from your tests. Maybe you are getting an error in your server (invalid authentication for example) which then won't return those headers (because it seems you only return them in the success case with status 200)? Maybe your authorization header is not sent because your library doesn't pass withCredentials: true to the XHR...Huberthuberto
A
0

I was having the same issue. My pre-flight OPTIONS request had all of the correct headers:

access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
access-control-allow-methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
access-control-allow-origin: *

So the browser started to accept requests after I added

access-control-allow-origin: *

To the response of the requests of the actual method I wanted to use (the non-preflight, eg: the GET, POST,etc method)

Antananarivo answered 6/12, 2020 at 17:16 Comment(0)
A
0

I just had this same problem pop up for me where I was working with Amplify and trying to secure the API Gateway to only be accessible to logged in users via Cognito.

The step that I had missed which you may have also missed is a bit of configuration within AWS API-Gateway. You need to go to the Gateway dashboard and create an 'Authorizer' which uses your Cognito User Pool. The token source is going to be whatever header label you are using for this (usually 'Authorization').

Creating new Authorizer

But you are not quite done. You then need to go to 'Resources' and change the Method Request to use your new Authorizer that you just created.

Using the new Authorizer with the resources

Hopefully after doing all this, you should be fine. If your user is logged in, and you add the Authorization header as you had:

let myInit = {
          headers: {
            Authorization: `Bearer ${(await Auth.currentSession())
              .getIdToken()
              .getJwtToken()}`
          }
        };

Then hopefully it all works out.

A video guide showing these steps can be found on here on Youtube, and starting around 10:50

Ali answered 6/12, 2021 at 22:3 Comment(0)
S
0

For anyone who is getting the same CORS error process as me: the preflight request was successful, and you configure everything with the '*' and the response headers allowed everything, but your actual request still got error. Please try to delete the AdminQueries api and its Lambda function and add everything again

Sinister answered 3/7, 2023 at 4:35 Comment(0)
E
0

If you are facing this error with AWS AMPLIFY then please check your Amplify configuration file.

  1. You might be missing identityPoolId if yes then add identityPoolId in your configuration.
  2. if identityPoolId is present then make sure that it is the correct one.

It is so because AWS AMPLIFY does not sign the request if idenitityPoolId is missing or incorrect.

I faced a similar issue and resolved my issue by this approach. Thanks

Edee answered 28/7, 2023 at 16:16 Comment(0)
N
-3

In case it helps anyone: our team fixed this by adding scope aws.cognito.signin.user.admin to Cognito Auth provider settings.

Niccolo answered 21/6, 2022 at 13:31 Comment(1)
Please could you provide some screenshot or guidance?Varro

© 2022 - 2024 — McMap. All rights reserved.