如何使用Node.js / Express + Passport + Websockets进行身份验证?

时间:2021-07-11 11:48:25

I am building an angular2-login-seed that uses Passport.js with OAuth strategies for authentication. Obviously the default method of authentication with these tools is use of an HTTP cookie signed by express. Passport, from what I can tell, manages the actual Set Cookie header so that express can authenticate each subsequent request via request.isAuthenticated() and access the data set by passport via req.session.passport.dataHere.

我正在构建一个angular2-login-seed,它使用Passport.js和OAuth策略进行身份验证。显然,使用这些工具进行身份验证的默认方法是使用由express签名的HTTP cookie。从我所知道的,Passport管理实际的Set Cookie标头,以便express可以通过request.isAuthenticated()验证每个后续请求,并通过req.session.passport.dataHere访问护照数据集。

I want to incorporate realtime data in the application via websockets. This of course means a socket stream coming from the server to the client. This communication is entirely separate from a regular HTTP server request meaning:

我想通过websockets将实时数据合并到应用程序中。这当然意味着从服务器到客户端的套接字流。此通信完全独立于常规HTTP服务器请求,这意味着:

  1. It does not contain the HTTP cookie that all HTTP requests contain

    它不包含所有HTTP请求包含的HTTP cookie

  2. Express does not broker the interaction with sockets, it is managed with whatever implementation is used in the backend (sock.js, socket.io)

    Express不代理与套接字的交互,它使用后端中使用的任何实现进行管理(sock.js,socket.io)

This makes it difficult to streamline authentication between HTTP requests to express, and websocket data to the backend as they are separate methods of communication.

这使得难以简化要表达的HTTP请求之间的身份验证,以及将websocket数据简化为后端,因为它们是单独的通信方法。

From my research, this leaves me with two options. One of which is to use a library to give my socket implementation (preferably sock.js over socket.io but I need to do more research) access to the express session. Then I could authenticate the socket connection however I want. Issue is I have no idea how I would get the express cookie into the stream from the front since javascript cannot access it (HTTP only cookie).

根据我的研究,这给我留下了两个选择。其中之一是使用库来实现我的套接字实现(最好是socket.io上的socket.js,但我需要做更多研究)访问快速会话。然后我可以验证我想要的套接字连接。问题是我不知道如何将快速cookie从前面获取到流中,因为javascript无法访问它(仅HTTP cookie)。

Another common solution I've seen people jump to is to use JWTs (JSON Web Tokens). Implementations revolving around this store the JWT in localstorage on the front end. This is so the SPA (in my case Angular2 services) could send it with every request for 'stateless' server authentication AND we could send it via a websocket to authenticate the websocket connection as well (the front end JS has access to localstorage obviously). A couple things that come to mind when thinking about this implementation:

我见过人们跳过的另一个常见解决方案是使用JWT(JSON Web令牌)。围绕此实现的实现将JWT存储在前端的localstorage中。这是SPA(在我的案例中Angular2服务)可以发送它与每个“无状态”服务器身份验证请求,我们可以通过websocket发送它来验证websocket连接(前端JS显然可以访问本地存储) 。在考虑这种实现时会想到几件事:

  1. Is it even possible to have Passport OAuth strategies use JWT instead of the regular session information? What modification would this entail? From what I can tell the Passport strategies use some form of OAuth1 or OAuth2 parent strategies for authentication which defaults to using cookies.

    是否有可能让Passport OAuth策略使用JWT而不是常规会话信息?这会带来什么样的改变?据我所知,Passport策略使用某种形式的OAuth1或OAuth2父策略进行身份验证,默认使用cookie。

  2. Would storing this vital information in localstorage open the application up to security breaches (XSS, CSRF, etc)

    将此重要信息存储在本地存储中会将应用程序打开以防止安全漏洞(XSS,CSRF等)

  3. If so, the most common workaround I've seen is to store the JWT in a cookie so it cannot be as easily accessed, spoofed, or forged. However this puts me back in the position I was in before using JWT, so might as well not bother.

    如果是这样,我见过的最常见的解决方法是将JWT存储在cookie中,这样就不会轻易访问,欺骗或伪造。然而,这让我回到了使用JWT之前的位置,所以不妨打扰。

  4. Does this mean I'd have to use some sort of state management store in the backend (Redis for example) to manage the authentication and decoding of the JWT body? (I know nothing about Redis, etc).

    这是否意味着我必须在后端使用某种状态管理存储(例如Redis)来管理JWT主体的身份验证和解码? (我对Redis一无所知等)。

The idea of connecting authentication between server HTTP requests and socket data is odd but seemingly vital to properly authenticating a socket connection. I'm a little surprised an easier method does not exist. I've done some research and have seen things such as socketio-jwt, express-jwt, etc however I don't know if this would be a manageable transition with my Passport strategies, or if it would be easier opening up express session data to the socket implementation, or if I'm going about it all wrong!

在服务器HTTP请求和套接字数据之间连接身份验证的想法很奇怪,但对正确验证套接字连接似乎至关重要。我有点惊讶一个不存在的简单方法。我已经完成了一些研究并且已经看过诸如socketio-jwt,express-jwt之类的东西,但是我不知道这是否可以通过我的Passport策略进行可管理的转换,或者是否更容易打开快速会话数据到套接字实现,或者如果我说错了!

Any help or guidance would be much appreciated thanks.

任何帮助或指导将非常感谢谢谢。

1 个解决方案

#1


0  

Then I could authenticate the socket connection however I want. Issue is I have no idea how I would get the express cookie into the stream from the front since javascript cannot access it (HTTP only cookie).

然后我可以验证我想要的套接字连接。问题是我不知道如何将快速cookie从前面获取到流中,因为javascript无法访问它(仅HTTP cookie)。

With express-socket.io-session the session auth is done on handshake, and the handshake is a http request, so even if your cookies are http-only it will work. (Tested by myself)

使用express-socket.io-session,会话auth在握手时完成,握手是一个http请求,所以即使你的cookie是http-only,它也会起作用。 (由我自己测试)

#1


0  

Then I could authenticate the socket connection however I want. Issue is I have no idea how I would get the express cookie into the stream from the front since javascript cannot access it (HTTP only cookie).

然后我可以验证我想要的套接字连接。问题是我不知道如何将快速cookie从前面获取到流中,因为javascript无法访问它(仅HTTP cookie)。

With express-socket.io-session the session auth is done on handshake, and the handshake is a http request, so even if your cookies are http-only it will work. (Tested by myself)

使用express-socket.io-session,会话auth在握手时完成,握手是一个http请求,所以即使你的cookie是http-only,它也会起作用。 (由我自己测试)