简体   繁体   English

Node/Express 的 Passport 身份验证中间件 - 如何保护所有路由

[英]Passport Authentication Middleware for Node/Express - How to Protect all Routes

Stack:堆:

Front End - Angular 12前端 - Angular 12

|-- Leveraging Angular/MSAL to integrate with Azure AD for authentication |-- 利用 Angular/MSAL 与 Azure AD 集成进行身份验证

Back End:后端:

|-- Node JS V14.17.6 |-- 节点JS V14.17.6
|-- Express 4.17.1 |-- 快递 4.17.1
|-- Passport-Azure-AD V4.3.0 (passport-azure-ad is a collection of Passport Strategies to help |-- Passport-Azure-AD V4.3.0(passport-azure-ad是Passport Strategies的集合,帮助

you integrate with Azure Active |-- Authentication Strategy - BearerStrategy (Protects APIs and Resources) Directory) |-- Passport V0.3.2 (Passport version leveraged by Passport-Azure-AD)您与 Azure Active 集成 |-- 身份验证策略 - BearerStrategy(保护 API 和资源)目录)|-- Passport V0.3.2(Passport-Azure-AD 使用的 Passport 版本)

Back End Project Structure (Excerpt shown for brevity) Root Directory |-- src |-- routers(Sub directory that holds all modularized routes per entity in individual .js files eg users.js, actions.js) |--index.js(Application entry point)后端项目结构(为简洁起见摘录) 根目录 |-- src |-- routers(子目录,每个实体的所有模块化路由保存在单独的 .js 文件中,例如 users.js、actions.js) |--index.js (应用程序入口点)

I'm looking for a way to protect all my routes/api endpoints, rather than having to apply the passport.authenticate to each route handler within each of the route endpoints which could be "N" number of routes per modularized route .js files as expressed above.我正在寻找一种方法来保护我的所有路由/api 端点,而不是必须将 Passport.authenticate 应用到每个路由端点内的每个路由处理程序,每个模块化路由 .js 文件可能是“N”条路由如上所述。 I have tried the following below to no avail.我尝试了以下方法无济于事。

  1. Within the index.js file, ie the applications entry point, in which I use eg const users = require('./routers/users') and app.use('/api/v1/users', users) to mount my route handlers, I introduced the following app.use(passport.authenticate('oauth-bearer', { session: false })) since passport is a middleware but no joy在 index.js 文件中,即应用程序入口点,其中我使用 const users = require('./routers/users') 和 app.use('/api/v1/users', users) 来安装我的路由处理程序,我引入了以下 app.use(passport.authenticate('oauth-bearer', { session: false })) 因为护照是一个中间件,但没有乐趣

  2. Within the modularized route handling files, I tried the following as well: router.all( '*' ,passport.authenticate('oauth-bearer', { session: false })) based on the express documentation, router.all should apply a middleware or provided function/handler at a path for all request methods and in this case the '*' should match all paths, but still this only worked for the base path '/' and not others in the file eg '/relationships'在模块化路由处理文件中,我也尝试了以下操作: router.all( '*' ,passport.authenticate('oauth-bearer', { session: false })) 基于快速文档,router.all 应该适用在所有请求方法的路径上的中间件或提供的函数/处理程序,在这种情况下, '*'应该匹配所有路径,但这仍然只适用于基本路径“/”,而不适用于文件中的其他路径,例如“/relationships”

If anyone can prescribe a way to protect all routes, it will be greatly appreciated.如果有人可以开出一种保护所有路线的方法,将不胜感激。

  1. The router.all() function is just like the router.METHOD() methods, except that it matches all HTTP methods (verbs). router.all()函数就像 router.METHOD() 方法一样,除了它匹配所有 HTTP 方法(动词)。

If I write, router.all('/users', callback) , it means, the callback will run for each method (GET,POST,DELETE,PATCH,PUT etc) for endpoint /users .如果我写, router.all('/users', callback) ,这意味着回调将为端点/users每个方法(GET、POST、DELETE、PATCH、PUT 等)运行。

If want to run it for each route, you would need to do something like this -如果想为每条路线运行它,你需要做这样的事情 -

router.all('*', callback)

  1. I like to use router.use() function, which is specifically for such use cases.我喜欢使用router.use()函数,它专门用于此类用例。 Suppose, I have 2 endpoints in my monitor routes.假设,我的监控路由中有 2 个端点。 If I want to put an authentication guard for both, I like to do this -如果我想为两者都设置一个身份验证保护,我喜欢这样做 -
const constant = require(__basePath + 'app/config/constant');
const router   = require('express').Router({
    caseSensitive: true,
    strict       : true
});
const monitor  = require(constant.path.module + 'monitor/monitor.controller');
const Passport      = require('passport');
const AuthGuard     = Passport.authenticate(['user', 'admin'], { session : false });

router.use(AuthGuard);

router.get(
    '/ping',
    monitor.ping
);

router.get(
    '/status',
    monitor.status
);

module.exports = {
    router: router
};

PS - Please ignore, constant and path related stuff, this is just for reference. PS - 请忽略, constantpath相关的东西,这仅供参考。

So after many a days, seeking a solution, I finally found the culprit as to why my implementation as stated above did not work.因此,经过许多天,寻求解决方案,我终于找到了为什么我的上述实施不起作用的罪魁祸首。 It boils down to the recent introduction of the wildcard '*' feature as it applies to MSAL/Angular's protectedResourceMap.归结为最近引入的通配符'*'功能,因为它适用于 MSAL/Angular 的 protectedResourceMap。 Leveraging the example above, the way this is implemented from the client(Angular V12) is by setting the aforementioned protected resource map to: 'http://localhost:3001/api/v1/*' and this one will logically think well in turn protect endpoints such as利用上面的例子,从客户端(Angular V12)实现的方式是将上述受保护的资源映射设置为:'http://localhost:3001/api/v1/*',这在逻辑上会很好地思考转保护端点,例如

  1. 'http://localhost:3001/api/v1/users' 'http://localhost:3001/api/v1/users'
  2. 'http://localhost:3001/api/v1/users/relationshp' 'http://localhost:3001/api/v1/users/relationshp'

but what I uncovered is that the Wildcard doesn't quite work as one will think, it pretty much will just match the first url above tagged (1.) as this is handled within the "users.js" router file by the router handler, base endpoint router.get('/', (req, res, next) => {...do something });但我发现通配符并不像人们想象的那样工作,它几乎只会匹配标记为 (1.) 上方的第一个 url,因为这是由路由器处理程序在“users.js”路由器文件中处理的, 基本端点 router.get('/', (req, res, next) => {...do something }); and will totally jettison the following router handler(Should match Second url above tagged (2.)), endpoint router.get('/relationships', (req, res, next) => {...do something });并将完全抛弃以下路由器处理程序(应该匹配标记为 (2.) 上方的第二个 url),端点 router.get('/relationships', (req, res, next) => {...do something }); which by the way is equally implemented within the "users.js" router file.顺便说一下,它同样在“users.js”路由器文件中实现。

Solution that saved the day client fix(Angular V12) was to first to remove the Wildcard asterix '*' as part of the Protected Resource Map configuration and just kept it as such : 'http://localhost:3001/api/v1/' and on the server side(NodeJs) per my requirements ie protect all routes was to apply the following solution to the entry point of the server solution "index.js" leveraging passport as a middleware applied to the application across the board: app.use(passport.authenticate('oauth-bearer', { session: false }));拯救一天客户端修复(Angular V12)的解决方案是首先删除通配符星号'*'作为受保护资源映射配置的一部分,并将其保留为:“http://localhost:3001/api/v1/ ' 并且在服务器端(NodeJs)根据我的要求,即保护所有路由是将以下解决方案应用于服务器解决方案“index.js”的入口点,利用通行证作为应用于全面应用程序的中间件:使用(passport.authenticate('oauth-bearer', { session: false })); this way not needing to implement same within each router handler file.这种方式不需要在每个路由器处理程序文件中实现相同的。 Hope this helps folks out there facing similar issues.希望这可以帮助那些面临类似问题的人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM