Разрешить гостевой режим (без авторизации) в Custom Authorizer в AWS
Я пытаюсь найти способ разрешить гостевой режим в настраиваемом авторизаторе в AWS.
По сути, я хочу добиться следующего сценария:
- если в запросе нет заголовка, активируйте лямбда-функцию, которая отвечает некоторыми данными
- если есть заголовок, то мой пользовательский авторизатор должен проверить токен JWT и либо, либо
. Затем активируйте лямбду, если она вернулась Allow
Я вижу, что могу добиться одного, но не обоих, т.е. я могу открыть конечную точку (полностью удалить), которая работает нормально, или я могу поставить
Тем не менее, я не вижу способа обойтись без заголовка.
Пример конфигурации в бессерверном режиме:
functions:
hello:
handler: handler.hello
events:
- http:
path: /hello
method: get
private: true
authorizer:
identitySource: method.request.header.Authorization # Can this be optional?
name: custom-authorizer
custom-authorizer:
handler: authorizer.handler
Из своего тестирования я могу подтвердить, что когда-то есть, и нет
Учтите, что в моем гостевом режиме я не хочу получать ответ от пользовательского шлюза API (это возможно и работает). Я хочу вызвать лямбда-функцию, как будто авторизации вообще не было.
Я прихожу к выводу, что это невозможно, и единственный выход - удалить
Любой совет?
4 ответа
Если вы настроите обработчик событий sls как * , а не
http
, затем является необязательным входом в
authorizer
(при условии, что бессерверный API соответствует API AWS).
Соответствующее CloudFormation
AWS::ApiGatewayV2::Authorizer
документы здесь .
Как вы уже поняли, если он настроен, но отсутствует в клиентском запросе, Apig возвращает
401
. Если вы опустите
identitySource
из конфига все запросы будут отправляться на ваш авторизатор лямбда. Затем ваша лямбда может обрабатывать три случая: нет токена, плохой токен, хороший токен.
* развертывается как
ApiGatewayV2
в AWS CloudFormation. Версия 2, как говорится в документации по Serverless, «быстрее и дешевле, чем версия 1». API и набор функций несколько различаются между «HTTP Api» (V2) и «Rest API» (V1), но
httpApi
является хорошим выбором по умолчанию.
Одно из решений, не упомянутых здесь, заключается в том, что вы можете отправить собственный заголовок авторизации с неаутентифицированными запросами (т. е.Authentication: "UNAUTHENTICATED"
), а затем оценивать запросы с этим конкретным заголовком как не прошедшие проверку подлинности.
Это требует координации с внешним интерфейсом, но обходит 401 и позволяет вам по-прежнему передавать контекст в нижестоящий API.
В ответ на ответ @fedonev вот полное решение:
- Использовать
HTTP API
вместоREST API
. - Обновлять
custom-authorizer
Давайте начнем с обновления в соответствии с новым и другим синтаксисом HTTP API:
Заменять
events.http
с
events.httpApi
и добавить
httpApi.authorizer
к
provider
. Обновлено
serverless.yml
:
provider:
httpApi: # Added
authorizers:
customAuthorizer:
type: request
functionName: custom-authorizer
functions:
hello:
handler: handler.hello
events:
- httpApi: # Changed
path: /hello
method: get
authorizer:
name: customAuthorizer # Changed
custom-authorizer:
handler: authorizer.handler
Далее нам нужно также обновить нашу функцию обработчика авторизатора. Ему по-прежнему нужно возвращать политику, как это было с REST API. Тем не менее... нет
event.authorizationToken
и нет
event.methodArn
больше (я оставил его закомментированным для справки):
module.exports.handler = async (event) => {
if (
!event.headers.authorization ||
event.headers.authorization === 'Bearer ABCDEF'
) {
// if (event.authorizationToken === 'Bearer ABCDEF')
return {
principalId: 'anonymous',
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: 'Allow',
Resource: event.routeArn,
// Resource: event.methodArn,
},
],
},
};
}
throw Error('Unauthorized');
};
Теперь мы видим, что у нас есть полный контроль над авторизацией, и мы можем проверить, есть ли токен:
!event.headers.authorization
(это имитирует гостевой режим) или если токен действителен:
event.headers.authorization === 'Bearer ABCDEF'
. Если токен недействителен, мы выдаем ошибку, которая дает
401 Unauthorized
как и ожидалось.
Наконец, стоит отметить, что все
headers
ключи в нижнем регистре и
principalId
является обязательным (по-прежнему, при использовании REST API авторизатор работал без него).
Разверните и наслаждайтесь!
Я только что столкнулся с похожей ситуацией с REST API и Lambda Authorizer. Мой авторизатор был настроен как авторизатор запроса, и я указал «авторизацию» в качестве обязательного заголовка. Это означает, что API Gateway не будет вызывать авторизатор, если заголовок отсутствует.
Чтобы разрешить анонимный доступ, я изменил заголовок с «авторизация» на «хост», и теперь API Gateway передает все запросы авторизатору. Надеюсь, это поможет.