AWS Lambda TokenAuthorizer响应错误排查(Node.js)
我正在开发一个用于API Gateway的Lambda JWT令牌授权器,验证请求中的令牌,但测试时遇到了配置错误。我的Lambda代码如下:
const blahJWT = require("@custom/blah/authentication/blah"); exports.handler = async (event, context, callback) => { try { let token = extractTokenFromHeader(event) || ''; const webAuth = new blahJWT(); await webAuth.authenticateWebToken(token); callback(null, 'Allow'); } catch (e) { console.log(e); // return {body: "Unauthorized", statusCode: 401}; callback('Unauthorized'); } }; function extractTokenFromHeader(e) { console.log(JSON.stringify(e)); console.log(e.authorizationToken); if (e.authorizationToken && e.authorizationToken.split(' ')[0] === 'Bearer') { return e.authorizationToken.split(' ')[1]; } else { return e.authorizationToken; } }
测试时传入有效令牌,出现以下错误:
Tue Sep 13 23:01:46 UTC 2022 : Authorizer result body before parsing: "Allow" Tue Sep 13 23:01:46 UTC 2022 : Execution failed due to configuration error: Invalid JSON in response: Cannot construct instance of `com.amazonaws.backplane.executioncore.frontend.authorizer.CustomAuthResponse` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('Allow') Tue Sep 13 23:01:46 UTC 2022 : AuthorizerConfigurationException
问题原因与解决方案
错误核心在于:API Gateway的自定义授权器不接受纯字符串响应,要求返回符合特定格式的JSON对象,用于生成访问策略。
正确的响应格式
API Gateway期望的授权响应必须包含principalId和policyDocument两个核心字段:
允许访问的响应
callback(null, { principalId: 'authenticated-user', // 可替换为实际用户ID等唯一标识 policyDocument: { Version: '2012-10-17', // 固定版本号 Statement: [ { Action: 'execute-api:Invoke', Effect: 'Allow', Resource: event.methodArn // 自动获取当前请求的API资源ARN,精准控制权限 } ] } });
拒绝访问的响应
callback(null, { principalId: 'unauthorized-user', policyDocument: { Version: '2012-10-17', Statement: [ { Action: 'execute-api:Invoke', Effect: 'Deny', Resource: event.methodArn } ] } });
修改后的完整代码
const blahJWT = require("@custom/blah/authentication/blah"); exports.handler = async (event, context, callback) => { try { let token = extractTokenFromHeader(event) || ''; const webAuth = new blahJWT(); await webAuth.authenticateWebToken(token); // 返回允许访问的策略 callback(null, { principalId: 'authenticated-user', policyDocument: { Version: '2012-10-17', Statement: [ { Action: 'execute-api:Invoke', Effect: 'Allow', Resource: event.methodArn } ] } }); } catch (e) { console.log(e); // 返回拒绝访问的策略 callback(null, { principalId: 'unauthorized-user', policyDocument: { Version: '2012-10-17', Statement: [ { Action: 'execute-api:Invoke', Effect: 'Deny', Resource: event.methodArn } ] } }); } }; function extractTokenFromHeader(e) { console.log(JSON.stringify(e)); console.log(e.authorizationToken); if (e.authorizationToken && e.authorizationToken.split(' ')[0] === 'Bearer') { return e.authorizationToken.split(' ')[1]; } else { return e.authorizationToken; } }
额外说明
event.methodArn包含当前请求的完整API资源ARN,使用它可以避免手动指定资源路径,提升代码通用性- 若需要向后端Lambda传递用户信息,可在响应对象中添加
context字段,比如context: { userId: 'xxx', roles: ['admin'] }
内容的提问来源于stack exchange,提问作者Talktomegoose
相关产品推荐
相关产品推荐

