我们有一个具有 MSAL 登录的前端反应应用程序,该应用程序使用 aws api 网关 api 端点进行后端操作。在登录过程之后,我想将承载令牌发送到 api 并对其进行身份验证。根据我在线阅读的内容,您可以使用 node.js 和 passport.authenticate() 来执行此操作。问题是试图在 aws api 网关中进行这项工作。所以我想出了一个通过 Authorizer lambda 进行身份验证的方案。1) 使用 aws-serverless-express 在 lambda 中将 express 作为 api 代理运行 2) 使用 passport-azure-ad 模块设置承载策略。3) 运行 passport.authenticate() 来验证令牌。4) 在 lambda 的有效令牌返回允许策略 5) api 请求将继续
我刚刚将以下文件和所需的节点模块放入 node.js lambda。所以这本质上是客户端和 api 之间的中间件。如果令牌有效,将允许请求通过。
在我的测试中,当它应用承载策略时出现此错误:
{ "name": "AzureAD: Bearer Strategy", "hostname": "169.254.43.173", "pid": 8, "level": 30, "msg": "authentication failed due to: token is not found", “时间”:“2020-08-24T23:48:35.497Z”,“v”:0 }
如果有一种更简单的方法来验证承载令牌,那就太好了。
Lambda index.js 文件:
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app')
const server = awsServerlessExpress.createServer(app)
exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context)
配置.js
'use strict';
const config = {
identityMetadata: "https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration",
clientID: "xxxxxxxxxxxxxxxxxxxx",
validateIssuer: true,
loggingLevel: 'info',
passReqToCallback: false,
ignoreExpiration: true
};
module.exports = config
app.js 文件
'use strict'
const express = require('express')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const passport = require("passport");
const config = require('./config');
const BearerStrategy = require('passport-azure-ad').BearerStrategy;
const bearerStrategy = new BearerStrategy(config, (token, done) => {
// Send user info using the second argument
done(null, {}, token);
}
);
const app = express();
app.use(passport.initialize());
const router = express.Router()
passport.use(bearerStrategy);
router.use(awsServerlessExpressMiddleware.eventContext())
var generatePolicy = function(effect, resource) {
var authResponse = {};
authResponse.principalId = 'user';
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 = "*";
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
}
var generateAllow = function(resource) {
return generatePolicy('Allow', resource);
}
router.get('/', passport.authenticate('oauth-bearer', {session: false}),
(req, res) => {
res.send(generateAllow(req.apiGateway.event.methodArn))
}
);
// The aws-serverless-express library creates a server and listens on a Unix
// Domain Socket for you, so you can remove the usual call to app.listen.
// app.listen(3000)
app.use('/', router)
// Export your express server so you can import it in the lambda function.
module.exports = app