繁体   English   中英

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

[英]Unable to use custom authorizer in API Gateway

我花了几天时间尝试使用带有 auth0 服务的自定义授权方来保护我的 API 网关。 我有我的 lambda 来验证我的持有者令牌,如果我在 AWS 控制台内调用它,Lambda 确实有效,当我创建自定义授权方时,我可以使用持有者令牌成功进行测试。

当我尝试将授权方附加到我的 API 网关方法并使用 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;
}

提前致谢!

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

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

这里的技巧是在配置“自定义授权方”时的“令牌源”中。 我在这里附上了一张图片,您可以在其中配置“令牌源”,该字段描述了自定义授权方的输入来自“授权标头”。 在此处输入图片说明 这样,您仍然可以从邮递员发送“授权”标头中的令牌,API 网关会在调用自定义授权方 lambda 时从“授权”标头复制它并将其复制到“授权令牌”输入字段。

在此处输入图片说明 希望很清楚。 如果您需要更多详细信息,请告诉我。

当您测试带有自定义授权方的 API 网关但从未触发 auth lambda 函数时,可能是由于令牌标头名称/令牌模式验证中的验证不成功。

我能够重现您的问题。

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

检查我让授权人工作的令牌头名称

我认为这可能是 AWS 门户中的一个新错误,因为我注意到他们不久前更改了 UI 以配置 API Gateway Authorizers。

很奇怪,HTTP 请求必须在名称为“AuthorizationToken”的标头中发送承载令牌。 如果您的 AWS 计划允许您访问他们的技术支持,您应该提醒他们有关此问题的信息。

就我而言,同样的错误(未触发 lambda,授权方失败)是由于我尚未部署 API。 我可能错了,但似乎为了测试授权器,您的 API 必须至少部署一次。

于是,我部署了 API,授权方测试开始工作。

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

  • APIGW 授权方响应被缓存
  • 您的配置需要其他地方的令牌。

对于缓存,您必须等到它过期或使用不同的令牌。 对于测试点,您可以删除缓存。 在后一种情况下,当请求在预期位置不包含令牌时,APIGW 授权方会自动拒绝missing token的请求。 在这些情况下,您的授权人甚至都不会被使用。

您可以在此示例中看到授权方配置查看identity sources中的Authorization header。

在此处输入图像描述

如果您没有指定授权 header,则该请求将被自动拒绝。

请求的另一个重要部分是Authorizer Type 您的代码正在验证event.typeTOKEN 但是TOKEN是遗留授权方类型。 当前的最佳做法是使用REQUEST 这会将整个请求公开给您的授权者,以便您可以直接正确使用request.headers.Authorization header。

处理这个问题的最佳方法仍然不是很明显,所以我通常推荐类似apigw 授权程序库的东西,然后将该库为您提供的解析与请求处理相结合。 有关如何处理请求的示例,请参见此处的apigw 授权方

暂无
暂无

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

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