gbv / login-server

Login and connect accounts with multiple identity providers
https://coli-conc.gbv.de/login/
MIT License
31 stars 32 forks source link

Find a way to associate WebSocket with session even when used cross-domain #9

Closed nichtich closed 5 years ago

nichtich commented 5 years ago

When sending API requests with axios or fetch, there is a way to tell the browser to send the cookie from the original domain with the request (for axios it's withCredentials, for fetch it's credentials: "include"). But there doesn't seem to exist an equivalent option for WebSockets (see my question on SO. Currently, the WebSocket uses the cookie from the initial request to associate itself with the sessionID, so it can send events that concern that particular session. If WebSocket does not support cross-domain cookies, we need to find an alternative option.

One way would be to request a token via axios first, for example a signed JWT that contains the sessionID, and use that with the WebSocket. It's one more step, but it would be a way to solve the issue.

stefandesu commented 5 years ago

Using the option with JWTs would also allow authenticated testing of the WebSocket (which I wasn't able to achieve yet).

stefandesu commented 5 years ago

I implemented the JWT idea. I will add tests tomorrow and also create an example that shows the workflow on how to use this.

stefandesu commented 5 years ago

A comprehensive example on how to use this authentication method and login-server in general can be found here: https://codepen.io/stefandesu/pen/vbaJwo

I will add more code comments there later.

Also, I found out that different browsers handle this issue differently. That's why I've added a check when a new WebSocket connection is created that looks up the sessionID in the database and preemptively sends an authenticated event if a session already exists. Therefore, most clients probably won't have to do the additional overhead of an extra request.

stefandesu commented 5 years ago

This idea breaks if the browser blocks third-party cookies (enabled in Safari by default, disabled in Chrome/Firefox by default). As far as I know, there is no way to fix this. This basically means that cross-domain WebSockets won't work AT ALL when third-party cookies are blocked.

I'd still continue with the WebSockets in general though. The master instance of Cocoda is running under the same domain as login-server, so there shouldn't be any problems there. Maybe we should move the dev instance of Cocoda to our servers as well so that, aside from testing, we shouldn't get any cross-domain problems anymore.

Alternatively, people using the dev branch need to be informed that authentication will only work with third-party cookies enabled.

What do you say @nichtich ?

stefandesu commented 5 years ago

Relevant article: https://blog.zok.pw/web/2015/10/21/3rd-party-cookies-in-practice/

Another workaround would be the following: In Cocoda (or other clients that use login-server), if the instance is on a different domain than the login-server instance, and third-party cookies are blocked (which needs to be detected somehow), the user needs to be directed to login-server and redirected back to Cocoda with, for example, a URL parameter which contains the token necessary to authenticate within the WebSocket.

As this is a very special case (users who block third-party cookies AND are using the dev branch or some other client application that's on a different server), I'd postpone this issue to the future.

nichtich commented 5 years ago

We should have the dev branch both at github.io and and coli-conc.de with different configuration. The application should basically be usable without login-server at the former without central login.

stefandesu commented 5 years ago

I'll close this issue for now. I agree that we should add another dev instance for Cocoda hosted on our servers which would work with login-server.