I'm developing a client-server application which uses WebSocket. I have implemented token-based authentication with JWT. Once my client has a valid token, a WebSocket connection is opened indefinitely.
Is it a good idea to send the token within each request? Is there any chance of anyone to hijack the connection?
My question actually applies to any TCP-based connection which requires authentication.
Is there any chance of anyone to hijack the connection? ... My question actually applies to any TCP-based connection which requires authentication.
Yes it is possible to hijack existing TCP connections or just be the man in the middle when you start a new one. The protection against this is not to send the authentication within each message because these could be simply replicated by the attacker. Instead use encryption, i.e. wss:// in case of WebSockets or TLS, IPSec or similar in other cases. These protect against both active man in the middle attacks (hijacking) and passive sniffing.
Related
The typical scenario:
The client sends his credentials to the server in a POST request using HTTPS.
The server verifies that the credentials are the right ones and authenticates the user. Thus it returns a JWT (JSON Web Token) to the client.
The client opens a non secured WebSocket connection (ws://). So the client and the server now have a channel to exchange data easily (the exact reasons don't matter here).
The user sends any kind of requests to the server through the WebSocket along with the JWT, so the server can verify that these requests are legit.
The server uses the WebSocket channel to return the data asked by the user after it successfully verified the JWT for each request.
Since we used HTTPS, we assume the JWT was not stolen when it was issued (HTTPS could be defeated but let's assume it's sane for our purpose).
The fact that we use a non secured WebSocket means that someone could sniff the traffic of the WebSocket channel and steal the JWT in a heartbeat. So we use a WebSocket Secure (wss://) instead and apply the same previous scenario.
Now that we are using a WebSocket Secure, do we need to keep sending the JWT in each request we make to the server when we use the WSS channel to do so? Or is the WebSocket Secure channel secured enough so both the server and the client are 100% sure (as long as TLS is not defeated) that this channel is legit?
In other words: once a WSS channel has been safely established, can we trust it? (until the connection is closed obviously)
I don't really understand how a WSS connection is established and how it works once it has been established. My understanding is: the critical part is the handshake, and once the handshake is done you can safely rely on the WSS channel (because it prevents MITM attacks using TLS, which WS doesn't do).
I read a lot of stuff these last days about all this but some concepts are still unclear. Any help will be greatly appreciated!
Websockets use a persistent TCP/IP connection.
Using wss is similar to using the HTTPS, which means that once the SSL/TLS handshake is complete, all Websocket data is "wrapped" (usually encoded) in TLS packages.
Assuming the TLS/SSL connection is secure, the Websocket connection will remain secure and could be (and probably should be) authenticated only once.
Hence, there's no reason to keep sending the JWT over and over again. It's a better solution to use the connection's persistent state in order to "assign" a user to the connection.
Side-Note: Although insecure, it would be better to send the JWT once even when using Websocket connection "in the clear" (ws://), since there are less opportunities to sniff out the JWT.
I have built a game server in nodejs using socket io.
I am planning to remove express and cookies from the authentication procedure and instead use webstorage and a client which attempts to log in during the socket io handshake.
However, I am using http and sending the user id and password in cleartext. Please, have mercy on me! I believe using https for the entire socket connection would add a huge overhead since updates are sent every 100ms. My current solution has worked for development, but I am sure it is insecure.
I should mention I have never set up/used https, so correct me if I am wrong regarding the overhead, which I know is a very debated topic. An ideal solution appears to be authenticating users over a https connection and then transmitting game state stuff over http, but I have no idea if or how this could be achieved.
Finally, I have 2 options for logging users in. I could allow the socket io connection on the server and just emit the log in credentials from the client. Then disconnect them if they are incorrect.
However, a cleaner solution would be to send the user id and pw in the http header for the handshake, and then authenticate the user from a socket.io middleware, but I am not sure if sending the data this way would be safe.
I do not think this is such a niche problem that a standard practice does not exist, however it may be to just use https. I believe there is no advantage to encrypting the users credentials as the data can still be snooped between the client and server. Any information on how I can achieve this is appreciated,
Or just point me in the right direction :)
Use one https connection for the login authentication and reply back to the client with a unique security token if the username/password is valid.
Use ordinary http connections for the rest of the dialog between client and server. Include the security token in the dialog if the client is requesting something that requires validation. Your client can store the security token in a cookie if you find that convenient, as the token can only be used for one session.
Have the server purge session tokens once a client signs off, or after the token has been idle for some period of time.
This is cheap and effective for medium-security applications. Variations on this scheme get used in many applications. It is not foolproof - a packet sniffer may be able to grab the security token in transit.
If the security token is constructed from a hash of the client IP address and a server timestamp, then it is easy for the server to validate the token in every message and very difficult for a 3rd-party to hijack the session.
In emacs/wanderlust, if one selects the 'clear' method of password transmission, but enables SSL for IMAP, is the password transmission secured by SSL encryption? Specifically, concern arises from the following para in the wanderlust Info manual:
There are two ways to use SSL. One is to start SSL negotiation just
after the connection establishment (generic way). The other one is to
start SSL negotiation by invoking STARTTLS command in the each session.
So is password transmission done before or after SSL encryption in the first method? If before, then does the second (STARTTLS based) method ensure encrypted password transmission?
The password is secure in either case.
The difference between these methods is in another aspect: The first method starts a TLS connection right after the TCP handshake, and before any IMAP exchange starts. Hence, it uses a different port than regular IMAP, but can be used with IMAP servers that do not have built-in TLS support, by simply tunneling their traffic.
With the second method however, the client connects to the regular IMAP port and starts an unencrypted IMAP exchange. However, before sending any credentials or any other private data it tells the server to upgrade the connection to a TLS connection, and only resumes the IMAP exchange (including password transfer) after this upgrade succeeded. This method allows to serve encrypted IMAP from the default IMAP port, but needs an IMAP server that can handle this IMAP protocol extension.
Nowadays, most servers support STARTTLS, so both methods are mostly equivalent. Use whatever Wanderlust uses as default.
I'm wondering how LDAP associates requests with a previous BIND request on a technical level.
For example you issue a BIND request to LDAP that authenticates you to do searches or whatever then you UNBIND.
How does LDAP associate your subsequent SEARCH/ADD etc. requests after the BIND?
I'm currently digging through a packet capture of a bunch of LDAP requests and I don't see the bindResponses returning a session token or anything like that ... does it just consider an IP authenticated or something?
Thanks if anyone can shed some light on the internal mechanism here!
edit: using SIMPLE auth BINDs
Are you talking to the LDAP server using UDP or TCP?
With TCP, it's simple - you do a BIND, then that TCP connection remains authenticated for any subsequent operations issued on the connection, until the connection closes or you issue an UNBIND.
is there a way for some one to sneak in the to see data if my service is over http and the caller in my case is hosted on http (i.e. service is on secure ssl host while caller is on simple http).
is that call secure or not?
Basic HTTP without any encryption or other means of obfuscating your content is just plain text going over the wire. Anyone with a bit of knowledge can trap that connection and just read everything that goes on.
I don't quite understand what you mean by the server is on secure host but the client is not? Either the conversation between those two is secured by SSL / HTTPS (but then BOTH ends need to participate), or not. If not - it's just clear text on the wire.
Yes if someone is able to sneak into your transmissions, they can workout if the messages are encrypted or not.
When you connect to a server marked with server side SSL (server marked with https), it sends a copy of its cert to the client (e.g. your browser) which verifies if its a genuine cert. This only confirms that the server is really what it says it is and not someone else masquerading.
This does not guarantee that no can intercept your message. They can intercept but wont be able to decrypt.