我花了几天时间尝试使用自定义授权者和 auth0 服务来保护我的 API 网关。我有 lambda 来验证我的不记名 token ,如果我在 AWS 控制台内调用 Lambda,那么 Lambda 确实可以工作,并且当我创建自定义授权方时,我可以使用不记名 token 成功进行测试。
当我尝试将授权者附加到我的 API 网关方法并使用 postman 和 auth0 提供的 token 测试请求时,它始终返回 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字段中包含不记名 token ,但是从Postman或任何其他客户端调用API网关时,您可以在授权 header 中发送“不记名 token ”,因为这是行业标准,AWS已支持它。
这里的技巧在于配置“自定义授权者”时的“ token 源”。我在此处附加了一个图像,您可以在其中配置“ token 源”,该字段描述了自定义授权者的输入来自“授权 header ”。 这样,您仍然可以从 postman 发送“Authorzation” header 中的 token ,API Gateway 会在调用自定义授权者 lambda 时从“Authorization” header 复制该 token 并将其复制到“authorizationToken”输入字段。
关于node.js - 无法在 API Gateway 中使用自定义授权方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46517032/