SvelteKit how to handle authenticated WebSocket connections - django

I have a Django backend that accepts WebSocket connections under a given url. The url takes a JWT token as parameter to authenticate users trying to use a certain websocket.
I'm trying to connect to a WebSocket from my SvelteKit frontend. The problem I'm having is that I can only access the Http-Only cookies containing my access & refresh key from within my +page.server.ts endpoint files. How would I go about authenticating the connection while also establishing a connection from the client side to access messages being sent via the WebSocket?
Currently I've been following this tutorial using a custom vite plugin as well as socket.io but it doesn't seem to be trying to achieve what I'm trying to work towards.
Any help, code samples and ideas on how to handle this problem would be very appreciated!

Related

Authentication and websockets

I'm doing this -
Load single page application - an apollo client is initialised with a websocket and http link. This happens when the user is logged out, let's say.
The user then logs in without a page reload. The graphql response now contains the session cookie.
Problem - whilst subsequent http requests include the session cookie the websocket connection does not.
How do people solve this problem?
I'm guessing either make all communication with the server via websockets, or, create a new apollo client upon successful sign in and use this for subscriptions.
This is for a chat app. I'm using http and websockets at the moment.

Can I rely on ConnectionId for security with API Gateway Websockets?

I'm working on a project where the backend is built with the serverless framework. Recently, I added a feature using API Gateway's websockets. However, I have my doubts about my particular implementation's security, and wanted to ask how valid they were.
I struggled to build authentication into my websocket routes. There was an authorizer feature, but unfortunately native Javascript APIs provide no way to edit headers in a Websocket message - this means I would have to submit authorization tokens in the url params, which I would prefer not to do.
I came up with a workaround. I have existing HTTP microservices set up on API Gateway with serverless, authenticated through AWS Cognito Identity Federation. My solution was to "piggyback" my websocket authentication onto my HTTP services, as follows.
My client opens a websocket connection, and receives back the connectionId assigned to it by API Gateway.
My client calls an HTTP route with the connectionId, which is authenticated with Cognito. This serves to let my backend know that this particular connectionId is authenticated. I push the connectionId and the Cognito identity to a database, along with other information. This way, later I can find what connectionIds are associated with a particular Cognito identity.
When a client wants to call a "secured" websocket method, the websocket method checks the lookup table to see if that connectionId is associated with the correct Cognito identity. If it is, then the method goes through. Otherwise, the connection is closed.
I found this resource at Heroku on websocket safety which recommends a similar, but not quite identical process: https://devcenter.heroku.com/articles/websocket-security
It recommends the following:
"So, one pattern we’ve seen that seems to solve the WebSocket authentication problem well is a “ticket”-based authentication system. Broadly speaking, it works like this:
When the client-side code decides to open a WebSocket, it contacts the HTTP server to obtain an authorization “ticket”.
The server generates this ticket. It typically contains some sort of user/account ID, the IP of the client requesting the ticket, a timestamp, and any other sort of internal record
keeping you might need.
The server stores this ticket (i.e. in a database or cache), and also returns it to the client.
The client opens the WebSocket connection, and sends along this “ticket” as part of an initial handshake.
The server can then compare this ticket, check source IPs, verify that the ticket hasn’t been re-used and hasn’t expired, and do any other sort of permission checking. If all goes well, the WebSocket connection is now verified."
As far as I can tell, my method are heroku's are similar in that they both use an HTTP method to authenticate, but differ because
1) Heroku's method checks for authentication upon opening, while mine checks afterwards
2) Heroku's method requires generating and storing secure tokens
I don't want to send authorization over the websocket, because I'd have to store it in url params, and I also do not want to generate and store tokens, so I went with my method.
However, I have a couple of doubts about my method as well.
1) Because I don't check authorization on websocket open, in theory this approach is vulnerable to a dDos attack, where an attacker simply opens as many sockets as they can. My assumption here is that the responsibility falls on API Gateway to prevent, with its Leaky Bucket algorithm.
2) My strategy hinges on the connectionId being secure. If an attacker were able to spoof this connectionId, then my strategy would no longer work. I assume this connectionId is issued internally within API Gateway to mark specific connections, and should not be vulnerable as a result. However, I wanted to double check if this was the case.
I would suggest looking into JWT's. It was kind of created for this purpose where you need to have some way to authenticate client-side requests without exposing credentials. It is fully self contained and allows you to not make a request to a database everytime you make a request to validate the user making the request: https://jwt.io/
JWT's are very easy to implement in Serverless and attach to a web socket connection request. You can then do something like add the user IP address to the payload of the JWT and validate that at request time to ensure that the user is 100% validated.

Identify URL of webpage when I can only receive API calls from the websites backend server

So I have a tricky problem of trying to somehow identify the url of a webpage, but I only have info on it's backend server that makes API calls to my server.
I have a server that receives API calls from another server running PHP. The clients PHP server receives information from a webform on their website. I am trying to the match API calls I receive with the webpage that submitted the data. Requesting the client to add a url in the API call will not guarantee that they haven't provided a fake one.
I was wondering if there is something I could do with a hidden iframe that could receive some sort of token or cookie from my server, then pass it to the PHP server who then includes it in the API call. Then I could match the url of the page I sent the token to with the API call.
Is this practical / possible? Any other suggestions of how to solve this problem??

Type of authentication when using HTTP and websockets

I have a website where I am using regular HTTP API requests and a websocket authenticated connection for realtime data.
I am using token authentication for API requests, authenticating websocket connection upon connection via header token.
I would however still like to somehow uniquely identify a "session", if a user was using the same token on two machines. Do I save a random string generated upon login along with the authentication token, to uniquely identify a session?
Or did I go about this the wrong way and is token authentication really just not appropriate for my case?
Because token authentication is just so much easier to implement on the frontend, as I am using React.

How can I access ejabberd REST API from server side

I am new to eJabberd, after setting up the server and be able to send messages between users I want to be able to create rooms from our backend server (not from our clients).
I read this article:
https://docs.ejabberd.im/developer/ejabberd-api/oauth/
But I did not understand how can I use the api from our server side (for example, to automatically create rooms for our users), how can I obtain a token for the server to use the API?
Thanks.
You should consider using mod_rest - http interface to post data to ejabberd. You can read more about configuration & examples here.
Do consider adding some restrictions so that only your server can use the http interface.