简体   繁体   English

如何从 API 网关自定义授权方抛出自定义错误消息

[英]How to throw custom error message from API Gateway custom authorizer

Here in the blue print says, API gateway will respond with 401: Unauthorized.蓝图说,API 网关将响应 401:未经授权。

I wrote the same raise Exception('Unauthorized') in my lambda and was able to test it from Lambda Console.我在我的 lambda 中编写了相同的raise Exception('Unauthorized')并且能够从 Lambda 控制台对其进行测试。 But in POSTMAN, I'm receiving status 500 with body:但是在 POSTMAN 中,我收到状态为500的正文:

{
  message: null`
} 

I want to add custom error messages such as "Invalid signature", "TokenExpired", etc., Any documentation or guidance would be appreciated.我想添加自定义错误消息,例如“无效签名”、“TokenExpired”等,任何文档或指导将不胜感激。

This is totally possible but the docs are so bad and confusing.这是完全可能的,但文档是如此糟糕和令人困惑。

Here's how you do it:这是你如何做到的:

There is an object called $context.authorizer that you have access to in your gateway responses template.您可以在网关响应模板中访问一个名为$context.authorizer的 object。 You can read more about it here: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html您可以在此处阅读更多信息: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

Here is an examample of populating this authorizer object from your authorizer lambda like so:这是从您的授权人 lambda 填充此authorizer人 object 的示例,如下所示:

 // A simple TOKEN authorizer example to demonstrate how to use an authorization token // to allow or deny a request. In this example, the caller named 'user' is allowed to invoke // a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke // the request if the token value is 'deny'. If the token value is 'Unauthorized', the function // returns the 'Unauthorized' error with an HTTP status code of 401. For any other token value, // the authorizer returns an 'Invalid token' error. exports.handler = function(event, context, callback) { var token = event.authorizationToken; switch (token.toLowerCase()) { case 'allow': callback(null, generatePolicy('user', 'Allow', event.methodArn)); break; case 'deny': callback(null, generatePolicy('user', 'Deny', event.methodArn)); break; case 'unauthorized': callback("Unauthorized"); // Return a 401 Unauthorized response break; default: callback("Error: Invalid token"); } }; var generatePolicy = function(principalId, effect, resource) { var authResponse = {}; authResponse.principalId = principalId; if (effect && resource) { var policyDocument = {}; policyDocument.Version = '2012-10-17'; policyDocument.Statement = []; var statementOne = {}; statementOne.Action = 'execute-api:Invoke'; statementOne.Effect = effect; statementOne.Resource = resource; policyDocument.Statement[0] = statementOne; authResponse.policyDocument = policyDocument; } // Optional output with custom properties of the String, Number or Boolean type. authResponse.context = { "stringKey": "stringval custom anything can go here", "numberKey": 123, "booleanKey": true, }; return authResponse; }

They key here is adding this part:他们在这里的关键是添加这部分:

// Optional output with custom properties of the String, Number or Boolean type.

        authResponse.context = {
            "stringKey": "stringval custom anything can go here",
            "numberKey": 123,
            "booleanKey": true,
        };

This will become available on $context.authorizer这将在 $context.authorizer 上可用

I then set the body mapping template in gateway responses tab like this:然后我在网关响应选项卡中设置正文映射模板,如下所示:

{"message":"$context.authorizer.stringKey"}

NOTE : it must be quoted注意:必须引用

finally - after sending a request in postman with Authorization token set to deny I now get back a payload from postman that looks like this:最后 - 在 postman 中发送请求并将Authorization令牌设置为拒绝后,我现在从 postman 取回一个有效负载,如下所示:

{
    "message": "stringval custom anything can go here"
}

I used @maxwell solution, using custom resource ResponseTemplates .我使用了@maxwell 解决方案,使用自定义资源ResponseTemplates For deny response see below:对于拒绝响应,请参见下文:

{
  "success":false,
  "message":"Custom Deny Message"
}

You can check this out here: https://github.com/SeptiyanAndika/serverless-custom-authorizer你可以在这里查看: https://github.com/SeptiyanAndika/serverless-custom-authorizer

I'm not sure what is causing the 500 message: null response.我不确定是什么导致了 500 message: null响应。 Possibly misconfiguration of the Lambda function permissions. Lambda function 权限可能配置错误。

To customize the Unauthorized error response, you'll set up a Gateway Response for the UNAUTHORIZED error type.要自定义未经授权的错误响应,您将为UNAUTHORIZED错误类型设置网关响应。 You can configure response headers and payload here.您可以在此处配置响应标头和有效负载。

Maxwell is mostly correct.麦克斯韦基本上是正确的。 I tried his implementation and noticed that his message should go from:我尝试了他的实现并注意到他的消息应该来自:

{"message":"$context.authorizer.stringKey"} {"消息":"$context.authorizer.stringKey"}

to

{"message":"$context.authorizer.context.stringKey"} {"消息":"$context.authorizer.context.stringKey"}

As noted by Connor far as I can see, the answer to the specific question - which mentions 401 related errors - is NO .正如康纳所指出的,据我所知,特定问题的答案 - 提到 401 相关错误 - 是NO

You can produce a generic 401 Unauthorized but you cannot alter the error message.您可以生成通用的401 Unauthorized但不能更改错误消息。

That is you can customise the 403 Forbidden (DENY) messages but not the 401's.也就是说,您可以自定义403 Forbidden (DENY) 消息,但不能自定义 401。

Note that I've used the NodeJS Lambda custom authorizers but not the Python version referenced in the question.请注意,我使用了 NodeJS Lambda 自定义授权方,但没有使用问题中引用的 Python 版本。

With my testing what i observed is, You cannot customize message when you throw exception from the lambda, You can have customized messages when you return DENY Policy message from the authorizer通过我的测试,我观察到的是,当您从 lambda 抛出异常时,您无法自定义消息,当您从授权方返回 DENY 策略消息时,您可以自定义消息

Here is how i am returning custom message when i DENY from the Authorizer, it in the detail field of authResponse.context returned from custom Authorizer这是我在授权方拒绝时返回自定义消息的方式,它位于从自定义授权方返回的authResponse.context详细信息字段中

you can also update status code to 401 instead of 403.您还可以将状态代码更新为 401 而不是 403。

在此处输入图像描述

This can be easily achieved by using the context.fail() function.这可以通过使用 context.fail() function 轻松实现。

Example:例子:

const customAuthorizer: Handler = (event, context: Context, callback: Callback) => {        
    authenticate(event)
        .then((res) => {
            // result should be as described in AWS docs
            callback(null, res);
        })
        .catch((err) => {
            context.fail("Unauthorized");
        });
}

This will return a 401 response with following body.这将返回带有以下正文的401响应。

{
    "message": "Unauthorized"
}

This can also be achieved by throwing an error:这也可以通过抛出错误来实现:

throw new Error('Unauthorized');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM