在 AWS 的自定义授权方中允许访客模式(无授权)

Allow Guest Mode (no authorization) in Custom Authorizer in AWS

我正在尝试找到一种方法在 AWS 的自定义授权器中允许 访客模式

基本上,我想要实现的是以下场景:

我看到我可以实现其中一个,但不能同时实现两个,即我可以打开端点(完全删除 authorizer),这可以正常工作,或者我可以放置 authorizer,这再次可以正常工作。

然而,当没有 Authorization header.

时,我看不到 by-pass custom-authorizer 的方法

无服务器中的示例配置:

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

根据我的测试,我可以确认一旦 authorization 存在并且请求中没有 Authorization header 那么我的 custom-authorizer 根本不会被触发并且 API 网关立即响应 401 Unauthorized

请注意,在我的访客模式下,我不想 获得自定义 API 网关响应(这是可能的并且有效)。我想像完全没有授权一样触发lambda函数。

我得出结论,这是不可能的,唯一的解决方法是删除 authorization,然后在 lambda 中编写一些自定义代码。

有什么建议吗?

如果您将 sls event handler 配置为 httpApi*,而不是 http,则 identitySource 是可选输入到 authorizer(假设无服务器 api 匹配 AWS api)。

相关的 CloudFormation AWS::ApiGatewayV2::Authorizer 文档是 here

如您所见,如果 identitySource 已配置但未出现在客户端请求中,则 Apig returns 401。如果您从配置中省略 identitySource,所有请求都将发送到您的授权者 lambda。然后,您的 lambda 可以处理三种情况:无令牌、坏令牌、好令牌。

* httpApi 在 AWS CloudFormation 中部署为 ApiGatewayV2。正如无服务器文档所说,V2“比 v1 更快、更便宜”。 api 和 feature set 在 "HTTP Api" (V2) "Rest Api" (V1) 之间有些不同,但 httpApi 是一个很好的默认选择.

跟进@fedonev 的回答是完整的解决方案:

  • 使用 HTTP API 而不是 REST API
  • 更新custom-authorizer

让我们开始根据更新的 不同 HTTP API 语法更新 serverless.yml

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

接下来,我们还需要更新我们的授权处理函数。它仍然需要 return 政策,就像它对 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 时,授权者在没有它的情况下工作)。

部署并享受!