在 AWS 的自定义授权方中允许访客模式(无授权)
Allow Guest Mode (no authorization) in Custom Authorizer in AWS
我正在尝试找到一种方法在 AWS 的自定义授权器中允许 访客模式。
基本上,我想要实现的是以下场景:
- 如果请求中没有
Authorization
header 则触发 lambda 函数以一些数据响应
- 如果存在
Authorization
header,那么我的自定义授权方应检查 JWT 令牌以及 Allow
或 Deny
。如果 custom-authorizer
返回 Allow
,则触发 lambda
我看到我可以实现其中一个,但不能同时实现两个,即我可以打开端点(完全删除 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 时,授权者在没有它的情况下工作)。
部署并享受!
我正在尝试找到一种方法在 AWS 的自定义授权器中允许 访客模式。
基本上,我想要实现的是以下场景:
- 如果请求中没有
Authorization
header 则触发 lambda 函数以一些数据响应 - 如果存在
Authorization
header,那么我的自定义授权方应检查 JWT 令牌以及Allow
或Deny
。如果custom-authorizer
返回Allow
,则触发 lambda
我看到我可以实现其中一个,但不能同时实现两个,即我可以打开端点(完全删除 authorizer
),这可以正常工作,或者我可以放置 authorizer
,这再次可以正常工作。
然而,当没有 Authorization
header.
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 时,授权者在没有它的情况下工作)。
部署并享受!