NodeJS 无法在API网关中使用自定义授权人

fnatzsnv  于 2023-01-01  发布在  Node.js
关注(0)|答案(4)|浏览(187)

我花了几天时间尝试使用自定义授权器和auth0服务来保护我的API网关。我有一个lambda来验证我的承载令牌,如果我在AWS控制台内调用它,Lambda确实可以工作,当我创建一个自定义授权器时,我可以成功地使用承载令牌进行测试。
当我尝试将authorizer附加到我的API Gateway方法,并使用postman和auth0提供的令牌测试请求时,它总是返回401状态代码。我在CloudWatch中阅读了我的日志,并查看了授权Lambda,无论何时我发出HTTP请求,它都不会触发。https://auth0.com/docs/integrations/aws-api-gateway/custom-authorizers/
这是我的授权lambda代码:
经办人:

'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);
    }
  });

};

下面是jwtManager:

"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;
}

先谢了!

mbskvtky

mbskvtky1#

我想描述一下我是如何解决这个问题的。
首先,自定义授权人始终需要authorizationToken字段中的承载令牌,但从Postman或任何其他客户端调用API网关时,您可以在授权头中发送“承载令牌”,因为这是一个行业标准,AWS支持它。
这里的技巧是在'令牌源'配置'自定义授权'。我已经附加了一个图像在这里,你可以配置'令牌源'这个字段描述了输入到自定义授权是从'授权头'。

这样,你仍然可以发送令牌'授权'头从 Postman ,并且API网关将从“授权”报头复制它,并且在调用定制授权者lambda时将它复制到“authorizationToken”输入字段。


希望你说清楚了。如果你需要更多的细节,请告诉我。

bgtovc5b

bgtovc5b2#

当您测试连接了自定义授权者的API Gateway,但auth lambda函数从未触发时,可能是由于令牌头名称/令牌模式验证中的验证不成功。
我可以重现您的问题。
只有当我在POSTMAN中将标题名称从“Authorization”更改为“AuthorizationToken”时,才能触发授权程序。
check the token header name I made the authorizer works
我认为这可能是AWS门户中的一个新错误,因为我注意到他们不久前更改了UI以配置API网关授权者。
非常奇怪的是,HTTP请求必须在名为“AuthorizationToken”的标头中发送承载令牌。如果您的AWS计划允许您访问他们的技术支持,您应该提醒他们这个问题。

rt4zxlrg

rt4zxlrg3#

在我的例子中,同样的错误(lambda未触发,authorizer失败)是由于我还没有部署API。我可能是错的,但似乎要测试一个授权器,您的API必须至少部署一次。
因此,我部署了API,授权程序测试开始工作。

0md85ypi

0md85ypi4#

它未被触发,这可能是由于以下两个原因之一:

  • 缓存APIGW授权者响应
  • 您的配置期望令牌位于其他位置。

该高速缓存的情况下,您必须等到它过期或使用不同的令牌。对于测试点,您可以删除缓存。在后一种情况下,当请求在预期位置不包含令牌时,APIGW授权器会自动拒绝使用missing token的请求。在这些情况下,甚至不使用您的授权器。
在本例中,您可以看到授权程序配置查看identity sources中的Authorization标头。

如果您没有指定授权头,那么请求将被自动拒绝。
请求的另一个重要部分是Authorizer Type。您的代码正在验证event.type是否为TOKEN。但是TOKEN是遗留授权者类型。当前的最佳实践是使用REQUEST。这将向您的授权者公开整个请求,以便您可以直接正确使用request.headers.Authorization报头。
处理这个问题的最佳方法还不明显,所以我通常推荐类似apigw authorizer库的东西,然后将这个库提供的解析与请求处理结合起来,在apigw authorizer中可以看到如何处理请求的例子。

相关问题