通过Lambda的API网关自定义授权程序的正确主要ID值?

时间:2016-02-17 17:02:20

标签: amazon-web-services jwt aws-lambda aws-api-gateway

我正在使用带有Lambda函数的API网关的新功能来使用自定义授权程序https://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html)。

授权人使用 JWT Tokens 来验证当前用户上下文和范围的令牌。一切正常,但有一个关于AWS策略的概念我无法从文档中找到。

自定义授权程序函数的输出必须是包含两个内容的对象:

  1. principalId - 有问题
  2. policyDocument - 一个有效的政策文档,其中包含允许用户授权访问Lambda资源,阶段等的语句。
  3. 现在,自定义授权程序的示例当前显示principalId变量的几乎任意值。但如果我正确思考,这个principalId应该对每个用户都是唯一的?并且可能具有与其关联的用户特定唯一值(例如token.userIdtoken.email)。

    如果是这样,那么对于我在下面提供的代码,如果JWT令牌有效,那么我无法访问userIdemail,并且不知道将principalId设置为什么。我暂时将其设置为user只是为了回复拒绝政策,以确保回复为403 Forbidden

    任何人都有关于为自定义授权者设置principalId的最佳做法的任何线索?

    var jwt = require('jsonwebtoken');
    var JWT_SECRET = 'My$ecret!';
    
    
    /**
     * Implicit AWS API Gateway Custom Authorizer. Validates the JWT token passed
     * into the Authorization header for all requests.
     * @param  {Object} event   [description]
     * @param  {Object} context [description]
     * @return {Object}         [description]
     */
    exports.handler = function(event, context) {
      var token = event.authorizationToken;
      try {
        var decoded = jwt.verify(token, JWT_SECRET);
        context.done(null, generatePolicy(decoded.id, 'Allow', 'arn:aws:execute-api:*:*:*'));
      } catch(ex) {
        console.error(ex.name + ": " + ex.message);
        context.done(null, generatePolicy('user', 'Deny', 'arn:aws:execute-api:*:*:*'));
      }
    };
    
    function generatePolicy(principalId, effect, resource) {
      var authResponse = {};
      authResponse.principalId = principalId;
      if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; // default version
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
      }
      return authResponse;
    }
    

1 个答案:

答案 0 :(得分:6)

principalId旨在表示授权进行API调用的任何实体的长期标识符。因此,如果您有一个现有的用户数据库,则每个用户可能都有一个唯一的标识符或用户名。你提到过用户',这可能很好。从功能上讲,如果启用CloudWatch Logs,则会记录principalId,也可以在映射模板的$ context中访问。

在功能设计方面,您有两种选择来处理“无效”功能。令牌。

  1. 如果您返回拒绝访问的有效策略,则可以通过缓存与令牌关联的策略来帮助您再次使用该令牌,从而减少Lambda调用次数。但是,客户可能会收到403并认为该令牌有效但他们无法访问他们所请求的资源。

  2. context.fail("Unauthorized")会向客户端发送 401 响应错误,这应该向他们表明令牌无效。这将有助于客户端,但如果客户端重复重放坏令牌,也会导致对函数的更多调用。此功能目前无法使用否定缓存,但提供适度保护的另一种方法是使用“身份验证异常”和“#39; identityValidationExpresion' - > http://docs.aws.amazon.com/apigateway/api-reference/resource/authorizer/#identityValidationExpression

  3. 此外,我强烈建议您将其迁移到基于apigateway-authorizer-nodejs蓝图的新Lambda函数,因为文档中的代码示例很少,仅用于说明。蓝图有很多注释记录了各种用途,例如失败(" Unauthorized")功能。