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

问题描述 投票:0回答:3

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

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

  • 如果请求中没有
    Authorization
    标头,则触发 lambda 函数来响应一些数据
  • 如果有
    Authorization
    标头,那么我的自定义授权者应检查 JWT 令牌以及
    Allow
    Deny
    。如果
    custom-authorizer
    返回
    Allow
  • ,则触发 lambda

我发现我可以实现其中一个,但不能同时实现两者,即我可以打开端点(完全删除

authorizer
),这可以正常工作,或者我可以放置
authorizer
,这又可以正常工作。

但是,当没有

custom-authorizer
标头时,我没有找到绕过
Authorization
的方法。

无服务器中的示例配置:

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
标头,那么我的
custom-authorizer
根本不会被触发,并且 API 网关会立即响应
401 Unauthorized

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

我得出的结论是这是不可能的,唯一的解决方法是删除

authorization
,然后在 lambda 中执行一些自定义代码。

有什么建议吗?

amazon-web-services aws-lambda authorization serverless
3个回答
1
投票

如果您将 sls 事件处理程序 配置为

httpApi
*,而不是
http
,则
identitySource
authorizer
的可选输入(假设无服务器 api 与 AWS api 匹配)。

相关的 CloudFormation

AWS::ApiGatewayV2::Authorizer
文档位于此处

正如您所经历的,如果

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

*

httpApi
在 AWS CloudFormation 中部署为
ApiGatewayV2
。正如 Serverless 文档所说,V2“比 v1 更快、更便宜”。 “HTTP Api”(V2)“Rest Api”(V1) 之间的 api 和 功能集 有所不同,但
httpApi
是一个不错的默认选择。


0
投票

跟进@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

接下来,我们还需要更新授权处理程序函数。它仍然需要像使用 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 时,授权者无需使用它即可工作)。

部署并享受!


0
投票

此处未提及的一个解决方案是,您可以选择发送带有未经身份验证的请求的自定义授权标头(即

Authentication: "UNAUTHENTICATED"
),然后将该特定标头的请求评估为未经身份验证。

这需要与前端协调,但可以避开 401,并允许您仍然将上下文传递到下游 API。

© www.soinside.com 2019 - 2024. All rights reserved.