我有几天尝试使用auth0服务使用自定义授权器保护我的API网关 . 我有我的lambda验证我的持票人令牌,如果我在AWS控制台内调用它,Lambda会工作,当我创建自定义授权器时,我可以使用Bearer令牌成功测试 .
当我尝试将授权程序附加到我的API网关方法并使用邮递员和auth0提供的令牌测试请求时,它总是返回401状态代码 . 我在CloudWatch中读取了我的日志,并且每当我发出HTTP请求时,它都没有触发授权Lambda . 我正在学习本教程: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;
}
提前致谢!
2 回答
当您使用附加的自定义授权程序测试API网关但从未触发auth lambda函数时,可能是由于令牌标头名称/令牌模式验证中的验证失败 .
我能够重现你的问题 .
只有在POSTMAN中将 Headers 名称从“Authorization”更改为“AuthorizationToken”时才能触发授权程序 .
check the token header name I made the authorizer works
我认为这可能是AWS门户中的一个新错误,因为我注意到他们不久前已经更改了UI以配置API网关授权程序 .
HTTP请求必须在名为“AuthorizationToken”的标头中发送承载令牌,这是非常奇怪的 . 如果您的AWS计划允许您访问其技术支持,则应提醒他们此问题 .
我想描述一下我是如何解决这个问题的 .
首先,自定义授权程序始终需要在authorizationToken字段中使用承载令牌,但是从Postman或任何其他客户端调用API网关时,您可以在授权标头中发送“承载令牌”,因为这是行业标准,AWS已经支持它 .
这里的诀窍是在'Token Source'中配置'custom authorizer' . 我在此处附加了一个图像,您可以在其中配置'Token Source'此字段描述自定义授权程序的输入来自'Authorization Header' .
这样,您仍然可以从postman发送'Authorzation'标头中的令牌,API Gateway会从'Authorization'标头复制它,并在调用自定义授权器lambda时将其复制到'authorizationToken'输入字段 .
希望很清楚 . 如果您需要更多详细信息,请告诉我们 .