Разрешить гостевой режим (без авторизации) в 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 сразу отвечает .

Учтите, что в моем гостевом режиме я не хочу получать ответ от пользовательского шлюза 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 передает все запросы авторизатору. Надеюсь, это поможет.

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