Amplify: заголовок CORS "Access-Control-Allow-Origin" отсутствует ошибка, хотя CORS включен в заголовках API Gateway и Lambda.

Я использую Amplify, и мой API-шлюз проксирует Lambda. Я включил CORS на своем/{proxy+}и развернул API. В моей функции Lambda я устанавливаю соответствующий заголовок в своей тривиальной функции:

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),
    }

Эта функция Lambda находится за ресурсом шлюза API, который аутентифицируется через Cognito.

Когда я вызываю свой API с помощью Amplify:

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

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

Я получаю ужасный заголовок CORS 'Access-Control-Allow-Origin', отсутствующий в моем GET запрос:

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).

Я вижу, что он вернулся в OPTIONS запрос:

Я даже протестировал в Postman, чтобы убедиться, что заголовки возвращаются:

Что я здесь делаю не так? Не похоже, что вызов проходит через шлюз API. Интересно, связано ли это с аутентификацией. Когда я тестирую Postman с использованием моих учетных данных IAM, он работает нормально, но в моем веб-приложении с использованием токена-носителя он не работает, как указано выше.

8 ответов

Я только что боролся с чем-то подобным. Здесь задается вопрос, почему браузер возвращает ошибку CORS при обращении к шлюзу API с помощью Amplify, несмотря на то, что заголовки CORS правильно настроены в конечной точке.

Помимо неправильной конфигурации заголовка CORS, Amplify / API Gateway выдает ошибку CORS, если некоторые аспекты запроса неверны. Я наткнулся на:

  • Используемый вами HTTP-глагол не существует для конечной точки.
  • Конечная точка, которую вы используете, не существует (например, опечатка)
  • Заголовок Content-Type неверен

Последнее вызывало у меня проблемы. Кажется, что Amplify.API.post а также Amplify.API.put оба отправляют Content-Type application/x-www-form-urlencodedпо умолчанию. Мой API ожидал application/json и результатом была ошибка CORS.

Когда используешь fetch()в js, когда я удалил Cognito Authentication из конечных точек OPTIONS шлюза API, это сработало. Chrome и Firefox не отправляют заголовки авторизации в OPTIONS. Хотя с усилителем все может быть иначе. Цитата: 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."

Для тех, кто получает тот же процесс ошибки CORS, что и я: предполетный запрос был успешным, и вы настраиваете все с помощью '*', а заголовки ответов разрешают все, но ваш фактический запрос все равно содержит ошибку. Попробуйте удалить API AdminQueries и его функцию Lambda и добавить все заново.

Если вы столкнулись с этой ошибкой при использовании AWS AMPLIFY, проверьте файл конфигурации Amplify.

  1. Возможно, вам не хватаетidentPoolId, если да, добавьтеidentPoolId в свою конфигурацию.
  2. если идентификаторidentPoolId присутствует, убедитесь, что он правильный.

Это происходит потому, что AWS AMPLIFY не подписывает запрос, если идентификатор idenitityPoolId отсутствует или неверен.

Я столкнулся с аналогичной проблемой и решил свою проблему с помощью этого подхода. Спасибо

Я предполагаю, что вы забыли обработать OPTIONSглагол, который используется для предварительного запроса, и вернуть там заголовок.

Вы отправляете Authorizationзаголовок, которого нет в списке разрешенных заголовков для "простых" запросов, поэтому выполняется предварительный запрос.

Кроме того, для получения учетных данных необходимо убедиться, чтоAccess-Control-Allow-Credentials: true заголовок также установлен.

Из фрагмента кода не видно, какой тип содержимого имеет тело запроса, но если это что-то другое, кроме application/x-www-form-urlencoded, multipart/form-data или text/plain (сказать, application/json), вам также необходимо внести в белый список Content-Type заголовок с использованием Access-Control-Allow-Headers: Content-Type.

У меня была такая же проблема. Мой предполетный OPTIONS запрос имел все правильные заголовки:

      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: *

Итак, браузер начал принимать запросы после того, как я добавил

      access-control-allow-origin: *

В ответ на запросы фактического метода, который я хотел использовать (не предполетный, например: GET, POSTи т. д.)

У меня только что возникла такая же проблема, когда я работал с Amplify и пытался защитить шлюз API, чтобы он был доступен только для зарегистрированных пользователей через Cognito.

Шаг, который я пропустил и который, возможно, пропустили и вы, — это небольшая настройка в AWS API-Gateway. Вам нужно перейти на панель управления Gateway и создать «Авторизатор», который использует ваш пул пользователей Cognito. token sourceбудет любой меткой заголовка, которую вы используете для этого (обычно «Авторизация»).

Но вы еще не совсем закончили. Затем вам нужно перейти в «Ресурсы» и изменить запрос метода, чтобы использовать ваш новый авторизатор, который вы только что создали.

Надеюсь, после всего этого у вас все будет хорошо. Если ваш пользователь вошел в систему, и вы добавляете заголовок авторизации, как у вас было:

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

Тогда, надеюсь, все получится.

Видеоруководство, показывающее эти шаги, можно найти здесь, на Youtube, начиная примерно с 10:50.

Если это кому-то поможет: наша команда исправила это, добавив область видимости.aws.cognito.signin.user.adminв настройки провайдера Cognito Auth.

Другие вопросы по тегам