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.
- Возможно, вам не хватаетidentPoolId, если да, добавьтеidentPoolId в свою конфигурацию.
- если идентификатор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.