缓存 AWS Lambda Authenticator 响应时出现 500 错误
我正在使用 无服务器堆栈,现在尝试添加 Lambda 自定义身份验证器以使用 Auth0 验证授权令牌并添加身份验证通过时将自定义数据发送到我的请求上下文。
此时一切都工作得很好,除了当我缓存同一令牌的身份验证器响应时。
我使用 5 秒缓存进行开发。具有有效令牌的第一个请求将按预期进行。 5 秒窗口中的下一个请求因神秘的 500 错误而失败,而没有到达我的代码。
授权方配置
// MyStack.ts
const authorizer = new sst.Function(this, "AuthorizerFunction", {
handler: "src/services/Auth/handler.handler",
});
const api = new sst.Api(this, "MarketplaceApi", {
defaultAuthorizationType: sst.ApiAuthorizationType.CUSTOM,
defaultAuthorizer: new HttpLambdaAuthorizer("Authorizer", authorizer, {
authorizerName: "LambdaAuthorizer",
resultsCacheTtl: Duration.seconds(5), // <-- this is the cache config
}),
routes: {
"ANY /{proxy+}": "APIGateway.handler",
},
});
授权方处理程序
const handler = async (event: APIGatewayAuthorizerEvent): Promise<APIGatewayAuthorizerResult> => {
// Authenticates with Auth0 and serializes context data I wanna
// forward to the underlying service
const authentication = await authenticate(event);
const context = packAuthorizerContext(authentication.value);
const result: APIGatewayAuthorizerResult = {
principalId: authentication.value?.id || "unknown",
policyDocument: buildPolicy(authentication.isSuccess ? "Allow" : "Deny", event.methodArn),
context, // context has the following shape:
// {
// info: {
// id: string,
// marketplaceId: string,
// roles: string,
// permissions: string
// }
// }
};
return result;
};
CloudWatch 日志
☝️ 每个未缓存的请求都会成功,状态代码为 200、集成 ID 和所有内容,正如预期的那样。 5 秒缓存期间的所有其他请求都会失败,并显示 500 错误代码且没有集成 ID,这意味着它无法到达我的代码。
有什么建议吗?
更新
我刚刚在 api-gateway.d.ts
@types 文件中找到了这个(请注意评论):
// Poorly documented, but API Gateway will just fail internally if
// the context type does not match this.
// Note that although non-string types will be accepted, they will be
// coerced to strings on the other side.
export interface APIGatewayAuthorizerResultContext {
[name: string]: string | number | boolean | null | undefined;
}
在让授权者首先工作之前我确实遇到了这个问题地方。我的 roles
和 permissions
属性是字符串数组,我必须将它们转换为纯字符串。然后就成功了。
你瞧,我刚刚运行了一个测试,删除了我为成功验证的令牌返回的上下文信息,现在缓存正在工作
I'm using serverless stack, now attempting to add a Lambda Custom Authenticator to validate authorization tokens with Auth0 and add custom data to my request context when the authentication passes.
Everything works mostly fine at this point, except for when I cache the Authenticator response for the same token.
I'm using a 5-second cache for development. The first request with a valid token goes through as it should. The next requests in the 5-second window fail with a mysterious 500 error without ever reaching my code.
Authorizer configuration
// MyStack.ts
const authorizer = new sst.Function(this, "AuthorizerFunction", {
handler: "src/services/Auth/handler.handler",
});
const api = new sst.Api(this, "MarketplaceApi", {
defaultAuthorizationType: sst.ApiAuthorizationType.CUSTOM,
defaultAuthorizer: new HttpLambdaAuthorizer("Authorizer", authorizer, {
authorizerName: "LambdaAuthorizer",
resultsCacheTtl: Duration.seconds(5), // <-- this is the cache config
}),
routes: {
"ANY /{proxy+}": "APIGateway.handler",
},
});
Authorizer handler
const handler = async (event: APIGatewayAuthorizerEvent): Promise<APIGatewayAuthorizerResult> => {
// Authenticates with Auth0 and serializes context data I wanna
// forward to the underlying service
const authentication = await authenticate(event);
const context = packAuthorizerContext(authentication.value);
const result: APIGatewayAuthorizerResult = {
principalId: authentication.value?.id || "unknown",
policyDocument: buildPolicy(authentication.isSuccess ? "Allow" : "Deny", event.methodArn),
context, // context has the following shape:
// {
// info: {
// id: string,
// marketplaceId: string,
// roles: string,
// permissions: string
// }
// }
};
return result;
};
CloudWatch logs
☝️ Every uncached request succeeds, with status code 200, an integration ID and everything, as it's supposed to. Every other request during the 5-second cache fails with 500 error code and no integration ID, meaning it doesn't reach my code.
Any tips?
Update
I just found this in an api-gateway.d.ts
@types file (attention to the comments, please):
// Poorly documented, but API Gateway will just fail internally if
// the context type does not match this.
// Note that although non-string types will be accepted, they will be
// coerced to strings on the other side.
export interface APIGatewayAuthorizerResultContext {
[name: string]: string | number | boolean | null | undefined;
}
And I did have this problem before I could get the Authorizer to work in the first place. I had my roles
and permissions
properties as string arrays, and I had to transform them to plain strings. Then it worked.
Lo and behold, I just ran a test right now, removing the context information I was returning for successfully validated tokens and now the cache is working ???? every request succeeds, but I do need my context information...
Maybe there's a max length for the context object? Please let me know of any restrictions on the context object. As the @types file states, that thing is poorly documented. This is the docs I know about.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是上下文对象值都不能包含“特殊”字符。
您的上下文对象必须类似于:
您不能将 JSON 对象或数组设置为上下文映射中任何键的有效值。唯一有效的值类型是字符串、数字和布尔值。
但就我而言,我需要发送一个字符串数组。
我试图通过 JSON 序列化数组来绕过类型限制,这会产生
"[\"valueA\",\"valueB\"]"
并且,出于某种原因,AWS 不喜欢它。TL;DR
解决我的问题的方法是使用
myArray.join(",")
而不是JSON.stringify(myArray)
The issue is that none of the context object values may contain "special" characters.
Your context object must be something like:
You cannot set a JSON object or array as a valid value of any key in the context map. The only valid value types are string, number and boolean.
In my case, though, I needed to send a string array.
I tried to get around the type restriction by JSON-serializing the array, which produced
"[\"valueA\",\"valueB\"]"
and, for some reason, AWS didn't like it.TL;DR
What solved my problem was using
myArray.join(",")
instead ofJSON.stringify(myArray)