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

Tom*_*tta 8 amazon-web-services jwt aws-lambda aws-api-gateway

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

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

Custom Authorizer函数的输出必须是包含两件事的对象:

  1. principalId- 有问题
  2. policyDocument - 带有语句的有效Policy文档,允许用户授权访问Lambda资源,阶段等.

现在,Custom Authorizers的示例当前显示principalId变量的几乎任意值.但如果我正确思考,这principalId对每个用户来说应该是唯一的吗?并且可能具有与其关联的用户特定唯一值(例如token.userIdtoken.email).

如果这是真的,那么我下面提供的代码,如果JWT令牌是不是有效的,那么我没有访问userIdemail,并没有什么线索设置principalId来.我暂时将它设置为user仅为Deny策略返回一些内容以确保响应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;
}
Run Code Online (Sandbox Code Playgroud)

Jac*_*AWS 6

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

在功能设计方面,您有两种处理"无效"令牌的选项.

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

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

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