Node.js 无法在API网关中使用自定义授权程序

Node.js 无法在API网关中使用自定义授权程序,node.js,amazon-web-services,aws-lambda,aws-api-gateway,Node.js,Amazon Web Services,Aws Lambda,Aws Api Gateway,我有几天的时间尝试使用auth0服务的自定义授权程序来保护我的API网关。我有我的lambda,它验证我的承载令牌,如果我在AWS控制台内调用lambda,lambda确实可以工作,并且当我创建自定义授权人时,我可以使用承载令牌成功测试 当我尝试将授权者附加到API网关方法并使用postman和auth0提供的令牌测试请求时,它总是返回401状态代码。我在CloudWatch中读取日志和授权Lambda,每当我发出HTTP请求时,它都不会被触发。我将学习本教程: 这是我的授权代码: 处理程序:

我有几天的时间尝试使用auth0服务的自定义授权程序来保护我的API网关。我有我的lambda,它验证我的承载令牌,如果我在AWS控制台内调用lambda,lambda确实可以工作,并且当我创建自定义授权人时,我可以使用承载令牌成功测试

当我尝试将授权者附加到API网关方法并使用postman和auth0提供的令牌测试请求时,它总是返回401状态代码。我在CloudWatch中读取日志和授权Lambda,每当我发出HTTP请求时,它都不会被触发。我将学习本教程:

这是我的授权代码:

处理程序:

'use strict';

let jwtManager = require("./jwt_manager");

module.exports.authenticate = (event, context, callback) => {

  jwtManager.validate(event, function (error, data) {
    if (error) {
      if (!error) {
        context.fail("Unhandled error");
      }
      context.fail(error);
    }
    else {
      console.log("SUCCEED");
      context.succeed(data);
    }
  });

};
这是JWT经理:

"use strict";
require("dotenv").config({ silent: true });

let jwksClient = require("jwks-rsa");
let jwt = require("jsonwebtoken");

module.exports.validate = function(params, callback) {
  var token = validateParams(params);

  var client = jwksClient({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 10,
    jwksUri: process.env.JWKS_URI
  });

  var decodedJwt = jwt.decode(token, { complete: true });
  var kid = decodedJwt.header.kid;

  client.getSigningKey(kid, function(error, data) {
    if (error) {
        console.log(error);
      callback(error);
    } else {
      var signingKey = data.publicKey || data.rsaPublicKey;
      jwt.verify(
        token,
        signingKey,
        { audience: process.env.AUDIENCE, issuer: process.env.ISSUER },
        function(error, decoded) {
            if (error) {
                console.log("ERROR");
                console.log(error);
                callback(error);
            }
            else {
                console.log(decoded);
                var response = {
                    principalId: decoded.sub,
                    policyDocument: getPolicyDocument("Allow", params.methodArn),
                    context: {
                        scope: decoded.scope
                    }
                }
                console.log(response);
                console.log(response.policyDocument);
                callback(null, response);
            }
        }
      );
    }
  });
};

function validateParams(params) {
  var token;

  if (!params.type || params.type !== "TOKEN") {
    throw new Error("Expected 'event.type' parameter to have value TOKEN");
  }

  var tokenString = params.authorizationToken;
  if (!tokenString) {
    throw new Error("Expected 'event.authorizationToken' parameter to be set");
  }

  var match = tokenString.match(/^Bearer (.*)$/);
  if (!match || match.length < 2) {
    throw new Error(
      "Invalid Authorization token - '" +
        tokenString +
        "' does not match 'Bearer .*'"
    );
  }

  return match[1];
}

 function getPolicyDocument(effect, resource) {

    var policyDocument = {};
    policyDocument.Version = '2012-10-17'; // default version
    policyDocument.Statement = [];
    var statementOne = {};
    statementOne.Action = [ 'execute-api:Invoke', 'lambda:Invoke'] ; // default action
    statementOne.Effect = effect;
    statementOne.Resource = resource.split('/')[0] + '/*';
    policyDocument.Statement[0] = statementOne;
    return policyDocument;
}
“严格使用”;
require(“dotenv”).config({silent:true});
设jwksClient=require(“jwks rsa”);
设jwt=require(“jsonwebtoken”);
module.exports.validate=函数(参数,回调){
var-token=validateParams(参数);
var client=jwksClient({
是的,
税率限制:对,
JWKSREQUEST精子分钟数:10,
jwksUri:process.env.JWKS_URI
});
var decodedJwt=jwt.decode(标记,{complete:true});
var kid=decodedJwt.header.kid;
client.getSigningKey(kid,函数(错误,数据){
如果(错误){
console.log(错误);
回调(错误);
}否则{
var signingKey=data.publicKey | | data.rsaPublicKey;
验证(
代币
签名键,
{访问群体:process.env.audium,发布者:process.env.issor},
函数(错误,已解码){
如果(错误){
控制台日志(“错误”);
console.log(错误);
回调(错误);
}
否则{
控制台日志(已解码);
var响应={
principalId:decoded.sub,
policyDocument:getPolicyDocument(“允许”,参数methodArn),
背景:{
作用域:decoded.scope
}
}
控制台日志(响应);
console.log(response.policyDocument);
回调(空,响应);
}
}
);
}
});
};
函数validateParams(参数){
var代币;
如果(!params.type | | params.type!=“令牌”){
抛出新错误(“预期”event.type“参数具有值标记”);
}
var tokenString=params.authorizationToken;
如果(!令牌字符串){
抛出新错误(“应设置“event.authorizationToken”参数);
}
var match=tokenString.match(/^Bearer(.*)$/);
如果(!match | | match.length<2){
抛出新错误(
“无效的授权令牌-”+
令牌串+
“'与'Bearer.''不匹配”
);
}
返回匹配[1];
}
功能getPolicyDocument(效果、资源){
var policyDocument={};
policyDocument.Version='2012-10-17';//默认版本
policyDocument.Statement=[];
var statementOne={};
statementOne.Action=['执行api:Invoke','lambda:Invoke'];//默认操作
声明一。效果=效果;
statementOne.Resource=Resource.split('/')[0]+'/*';
policyDocument.Statement[0]=statementOne;
退还保单文件;
}

提前谢谢

当您测试连接了自定义授权器的API网关但从未触发auth lambda函数时,很可能是由于令牌头名称/令牌模式验证中的验证失败

我可以复制你的问题

只有当我在POSTMAN中将标题名称从“Authorization”更改为“AuthorizationToken”时,才能触发授权人

我认为这可能是AWS门户中的一个新错误,因为我注意到不久前他们更改了UI以配置API网关授权程序


非常奇怪的是,HTTP请求必须在名为“AuthorizationToken”的头中发送承载令牌。如果您的AWS计划允许您访问他们的技术支持,您应该提醒他们这个问题。

我想描述一下我是如何解决这个问题的

首先,自定义授权人始终需要authorizationToken字段中的承载令牌,但从Postman或任何其他客户端调用API网关时,您可以在授权标头中发送“承载令牌”,因为这是行业标准,AWS支持它

这里的诀窍在于配置“自定义授权器”时的“令牌源”。我在这里附加了一个图像,您可以在其中配置“令牌源”。该字段描述自定义授权者的输入来自“授权头”。 这样,您仍然可以从postman发送“Authorization”标头中的令牌,API网关将从“Authorization”标头复制该令牌,并在调用自定义授权器lambda时将其复制到“authorizationToken”输入字段


希望一切都清楚。如果您需要更多详细信息,请告诉我。

在我的情况下,相同的错误(lambda未触发,授权人失败)是由于我尚未部署API。我可能错了,但似乎要测试授权者,您的API必须至少部署一次


因此,我部署了API,授权人测试开始工作。

您是否尝试打印策略声明并确保它们具有正确的Id?我不确定这与我的错误有关,因为我执行请求时不会触发Lambda,因此API网关从未收到LambdaHey人的响应,您是否也将method.request.header.AuthorizationToken作为令牌源,还是将其保留为method.request.header.Authorization,并按照图像中显示的方式发送了标头?顺便说一句,感谢您的帮助。显然,我们在10月份测试自定义授权程序时收到的HTTP错误代码401是由于AWS的一些暂时性错误造成的,当我们在自定义授权程序中将“authorization”指定为令牌源时,在请求进入auth lambda函数之前,AWS的验证失败