websocket reconnect using session id - javascript

I'm using Java and Websocket API for my application
This is the problem I face :
I open a websocket connection to connect through certain server :
ws = new WebSocket(targetURL);
When I send every message using ws, I always check the state of the ws first, by :
if(ws.readyState == 1) {
ws.send(request);
} else {
alert("THE CONNECTION IS CLOSED. PLEASE REFRESH YOUR BROWSER.");
}
I saved an information in my EndPoint during the communication between client and server. But sometimes, when I want to send message from client, the state is not 1, which means that the ws is no longer open (CMIIW). If I try to connect again using ws = new WebSocket(targetURL), it will create a new connection, thus the information in my EndPoint become lost.
So my question is :
Is there any way to reconnect a closed connection of Websocket using Session ID or any other unique ID so that the information in my EndPoint can be preserved?
Thank you

WebSockets use a HTTP handshake, and it will send whatever cookie they have for that origin. So a way of doing it, is assign a cookie to you clients, and they will forward it on connection. You could even set the cookie in the handshake response, if the framework you are using it allows it. You can use that cookie on connection to figure out the ID or assign a new ID if no cookie.
Other option is to create for example your own "hello" protocol, where the browser has to send a special command before start, indicating its ID if any, or just an null ID if it is first time.
But aside of the cookie, there is not built-in mechanism for that.

Related

Is it dangerous to establish WebSocket connection in a js file?

So, basically, I have this code :
let socket = new WebSocket('ws://localhost:8080/server.php');
socket.onopen = () => {
console.log('connection established !');
}
I use this code to establish a connection for a Real-Time Quiz. But after going to the Sources page of my inspector, I can see the whole javascript code in my browser, including ws://localhost:8080/server.php. Is it dangerous to show it (unintentionally) ? If someones creates a script and puts in it the same url (not localhost, it's just an example), can he receive/send data to the server ?
yes,it is dangerous. u can:
verify the client http request header for example 'Origin'. make sure the client website is the right client website.
use a TSL websocket service, visit to the server over SSL. So the protocol is changing to: wss://
give the client a request token, put this token in header or in post data, the server verify this token.
check the request times of a client in limited time. make sure a specific client won't request too frequently

Connect client socket to a cookie

I am making a chat program.
I am using an Nginx server and NodeJS.
I have setup a websocket via ssl and that works fine.
I have decided to use cookies for authentication.
There are two functions which are crucial:
mconnection.prototype.make_server_https=function(){
console.log('Make server https');
var cthis=this;
var server_https=modules.https.createServer({
key: this.ssl_key,
cert:this.ssl_cert,
ca:this.ssl_ca
},(request,response)=>{
console.log('### CreateServer ###');
console.log('CreateServer, Request:');
console.log(request);
console.log('CreateServer, Response:');
console.log(response);
console.log('######');
and
mconnection.prototype.make_server_websocket=function(){
var server_websocket=new modules.ws.Server({server:this.server_https});
var cookie = require("cookie");
var cthis=this;
//whenever a new client connects with the server.
server_websocket.on('connection', function(client_socket, request){
console.log('### On Connection ###');
console.log('OnConnection, Client Socket:');
console.log(client_socket);
console.log('OnConnection, Request:');
console.log(request);
console.log('######');
If I do state the port number in the client url,function make_server_https gets run and inside there i can access the cookie and set it via the response object.
but in the original url,function make_server_websocket gets run, and there i have access to the client_socket on the server. But there it seems i dont have access to the cookies.
I need to client_websocket to start the connection with this given client. And I need to tie it somehow with the cookies login information.
But i never have both at the same time so i dont get how i could connect them to make the login happen.
I am probably misunderstanding something, any help in the right direction would really be appreciated.
you have to serve you index page from node server using GET then when the request reaches backend you will have response object which can then be used to SET-COOKIE if not set from backend.
And after GET request is complete COOKIE will be added in browser, when next request is made for websocket connection COOKIE will be added to the request in REQUEST HEADERS by the browser which will be available in backend through request object.
And if you decide to use it in login system then you can SET-COOKIE on successfull login.
i got it. its an event called on headers, not on connection. and there i can just push onto the headers.

WebSockets and HTTP headers

I am trying to figure out how to add a header with an authorization token to a WebSocket connection, after it has been established. Basically, to use a cookie in order to validate each message in the connection.
There is a great discussion at HTTP headers in Websockets client API already, yet it did not really help me.
One of the the suggestions there was to do:
document.cookie = 'X-Authorization=' + token + '; path=/';
Unfortunately, it did not help me.
func handler(ws *websocket.Conn, h *Hub) {
go h.run()
h.addClientChan <- ws
for {
config := ws.Config()
fmt.Println("Headers length:", len(config.Header))
...
Shows a map with 0 elements before and after I add the cookie.
Is it possible to alter WebSocket connection headers, after the connection has been established?
Do I even need to add an authorization token to a WebSocket connection, provided I authenticate each time, or is it only useful to re-establish a connection and just a useless check after the fact?
Is it possible to alter WebSocket connection headers, after the
connection has been established?
You can't set a cookie upon receipt of a WebSocket message. Once the WebSocket connection has been established, it's an open TCP socket and the protocol is no longer http, thus there is no built-in way to exchange cookies.
You can use authorizathion on the first http request, where both sides establish protocol for exchange data.

Javascript websocket client library which can pass custom headers in handshake request

I need a javascript library to connect to my web-socket server which is implemented using python twisted. I tried Native javascript web-socket client but it doesn’t have the option to pass custom headers as per this link. My web-socket server does authentication by taking auth_token from handshake header as in Oauth2 standard. Is there any javascript library available for web-socket clients which allows to pass custom header while connecting ?
I'm sorry to be the bearer of bad news... but - as mentioned both in the question you are referencing and as you can learn from the standard Websocket API (this isn't an external library, it's what comes with the browser)... you cannot set custom headers for websocket connections.
The WebSocket(url, protocols) constructor takes one or two arguments. The first argument, url, specifies the URL to which to connect. The second, protocols, if present, is either a string or an array of strings. ... Each string in the array is a subprotocol name. The connection will only be established if the server reports that it has selected one of these subprotocols. ...
But, all is not lost.
Since this is YOUR websocket server, you have options:
I'm pretty sure that OAuth2 uses the token as a parameter for a GET or POST request and NOT as a custom header. This means that (maybe) you can pass the token as part of the connection string, i.e.:
websocket = new WebSocket('wss://my.server.com/?access_token=secret_acess_token');
Passing the session token like so might not be ideal and could pose a security risk... so I would go with the second options here:
New websocket connections (unless my browsers are special) are initiated with the same cookies that the main connection was established with - this means that all the cookies and session data from the Http layer is accessible to the websocket layer....
So, It's possible to set a unique cookie - or, even better (assuming your http and websocket share the same codebase and work well together), set an authentication token within a server-side session storage - and use that data to authenticate a connection or to refuse it.
Since I'm no Python expert, here's a quick demo using Ruby's Plezi framework (I'm the author):
require 'plezi'
class DemoCtrl
# this is the Http index page response
def index
response.write "#{cookies[:notice]}\n\n" if cookies[:notice] && (cookies[:notice] = nil).nil?
#returning a string automatically appends it to the response.
"We have cookies where we can place data:\n#{request.cookies.to_s}\n"
end
# the login page
def login
cookies[:my_token] = "a secret token"
cookies[:notice] = "logged in"
redirect_to :index
end
# the logout page
def logout
cookies[:my_token] = nil
cookies[:notice] = "logged out"
redirect_to :index
end
# a Plezi callback, called before a websocket connection is accepted.
# it's great place for authentication.
def pre_connect
puts "Websocket connections gave us cookies where we can place data:\n#{request.cookies.to_s}\n"
return false unless cookies.to_s[:my_token] == "a secret token"
# returning true allows the connection to be established
true
end
def on_message data
puts "echoing #{data}"
response << "echo: #{data}"
end
end
# setup the route to our demo
Plezi.route '/', DemoCtrl
# Plezi will start once the script is finished.
# if you are running this in irb, use:
exit
visit: http://loaclhost:3000/
to try and initiate a websocket, open up the web inspector and run the following script in the console:
ws = new WebSocket("ws://localhost:3000/"); ws.onopen = function(e) { console.log("open"); }; ws.onmessage = function(e) { console.log(e.data);};
ws.send("Go Bears");
This should FAIL, because we didn't authenticate yet...
visit http://loaclhost:3000/login and try again.
Now it should work.
Try http://loaclhost:3000/logout if you feel like it.

Notification in javascript - similar to new emails in gmail

I am creating a widget which will update some live NEWS happening. I want to push notification to the widget everytime I get some new information in my database. It is similar to live feed. I am unsure how to start this one in javascript.
I donot want to poll every nth second to get the information. I want the server to push information to the client everytime the server gets a new information.
It is similar to gmail. You get an email even without refreshing the page.
Any pointers will be definitely helpful.
You basically have 2 choices, what I can think of:
Using HTTP, you can ask the server every x second, if it has any new information, and if it does, then load & show it. If you are using HTTP, the server can't contact the client, it can only answer the clients requests.
Using sockets, you can create a 2 way communication, both the client can send data to the server, and the server can send data to the client. This way the server can send the information as soon, as possible. Here you can find information about the supported browsers.
Intermediate Node server can help to separate the business logic from polling operations.
Needs to install these packages - socket.io, express, request
npm install <package_names>
To get request data from node :
var socket = io.connect('http://localhost:3000');
socket.emit('pollNodeServer',JSON.stringify(requestToServer));
On server :
var http = require('http'),
request = require('request'),
app = require('express')(),
server = require('http').Server(app),
io = require('socket.io')(server);
server.listen(3000);
console.log('Server started at port 3000');
var options = {
headers : {
'Content-Type' : 'application/json',
'User-Agent' : 'request'
}
};
socket.on('pollNodeServer', function(data, callbackfn) {
requestServer(data,socket,callbackfn);
});
Reply from server :
socket.emit('returnJobs',JSON.parse(body));

Categories