need to send error to unauthorized user in socket.io - node.js

as the title is obvoius i need to send back some error message for unauthorized user and i need to know how to achive this for example i need to send this message to user
you dont have any username to begin chat
and print it in users browser how should i do that? the client side code is something like this
//this is the client side code
var socket = io.connect('http://localhost', { resource: '/chat/app.js' });
// on connection to server, ask for user's name with an anonymous callback
socket.on('connect', function(){
// call the server-side function 'adduser' and send one parameter (value of prompt)
socket.emit('adduser')
});
socket.socket.on('error', function (reason){
console.log('Unable to connect Socket.IO', reason);
});
but the reason which i get in console is
Unable to connect Socket.IO handshake error
how should i print the message which is the cause of user is nothing get authorized?
this is the server side code
var io = require('socket.io').listen(80);
io.configure(function (){
io.set('authorization', function (handshakeData, callback) {
// findDatabyip is an async example function
findDatabyIP(handshakeData.address.address, function (err, data) {
if (err) return callback(err);
if (data.authorized) {
handshakeData.foo = 'bar';
for(var prop in data) handshakeData[prop] = data[prop];
callback(null, true);
} else {
//THIS IS THE MESSAGE *********************************************
callback('you dont have any username to begin chat', false);
}
})
});
});

To send the error back to the user you must modify the error function on manager.js (socket.io\lib\manager.js; line 768 approx) from this
function error (err) {
writeErr(500, 'handshake error');
self.log.warn('handshake error ' + err);
};
to this
function error (err) {
writeErr(500, /*'handshake error'*/ err);
self.log.warn('handshake error ' + err);
};

Related

Angular 6 authentificate client after server restart socket.io socketio-jwt

Id like to auth eacht socket.io event on server side.
When i open angular page first, call method initSocket(login: Login), its ok.
Authentification successfull and i can send a message to server.
But if i restart server, angular reconnect to server by Htttp, but cant send a message by socketio.
In my server no messages in logs.
It seems that socketio-jwt block an clients message.
If i press F5 on client side its still ok again.
How to solve it without refreshing a page?
It seems taht i have to pass a token to each event on client side, after connection established to, but i dont know how to do it.
Angular 6:
public initSocket(login: Login): void {
this.socket = socketIo(SERVER_URL);
console.log('Socket init at' + SERVER_URL);
this.socket.emit('authenticate', { token: this.login.token });
this.socket.on('authenticated', function () {
console.log('socket is jwt authenticated');
});
this.socket.on('unauthorized', function (error, callback) {
if (error.data.type === 'UnauthorizedError' || error.data.code === 'invalid_token') {
// redirect user to login page perhaps or execute callback:
callback();
console.error('Users token has expired');
}
});
this.socket.on('disconnect', function (error) {
console.error('socket disconnect', error);
});
this.socket.on('connect_failed', function (error) {
console.error('socket connect_failed');
});
}
Server side:
io.sockets
.on('connection', socketioJwt.authorize({
secret: environment.secret,
timeout: 15000,
callback: false
})).on('authenticated', function (socket) {
clients[socket.decoded_token.id] = socket.decoded_token.login;
console.error('Connected: ', socket.decoded_token.login);
socket.on('message', async function (data) {
try {
// Проверка что пользователь пишите от себя
if (data.from === socket.decoded_token.id) {
data.totalCount = await db_helper.saveMessage(data);
if (clients[data.from] && clients[data.to]) {
io.sockets.connected[clients[data.to].socket].emit("message", data);
console.log("Sending from: " + clients[data.from].name + " to: " + clients[data.from].name + " '" + data.text + "'");
} else {
console.log('User does not exist: from=>', data.from, ':', clients[data.from], 'to=>', data.to, ':', clients[data.to]);
}
}
}
catch (error) {
console.error(error.message);
}
});
//Removing the socket on disconnect
socket.on('disconnect', function () {
});
});
This is because whenever your server/client goes offline, a new socket is created for re connection purpose and to establish a new connection i.e re connection, Server disconnects all it's previous connection from the same client, this process is asynchronous and thus is not visible to developers easily.
I would have also checked if my socket reconnection which is done is reconnected to the , by default socket reconnects to the port your client is connected to.
if that's the case then you need to reconnect with the help of io (socket manager)
There is also a possibility that your client re connection is set to false, you can check your socket properties by consoling it as follows:
this.socket.on('disconnect', function (error) {
console.log('disconnected', this)
//this sets whether the re connection is allowed or not
this.io._reconnection = true;
});
this.socket.on('reconnect', (error, callback) => {
console.log('reconnect succesfully', this);
//connect to the previously connected socket.
this.io.socket.reconnect()
});

Sails.js: stream socket and send to controller

I'm writing a REST API in Sails.js and alongside the regular HTTP routes, I need the application to listen for notifications on a socket from Salesforce.
I have a controller with some logic but I don't know how to get it to subscribe to the socket on startup, so right now nothing is reaching it.
Controller:
pushTopicHandler: function(req, res) {
if (!req.isSocket) {
return res.badRequest();
}
var nforce = require('nforce');
var org = nforce.createConnection({
clientId: sails.config.client_id,
clientSecret: sails.config.client_secret,
redirectUri: sails.config.callback_url + '/oauth/_callback',
mode: 'multi',
environment: 'sandbox'
});
org.authenticate({ username: sails.config.sfUsername, password: sails.config.sfPassword }, function(err, oauth) {
if(err) return res.serverError(err);
var str = org.stream({ topic: sails.config.push_topic, oauth: oauth });
str.on('connect', function(){
console.log('Connected to pushtopic: ' + sails.config.push_topic);
});
str.on('error', function(error) {
console.log('Error received from pushtopic: ' + error);
});
str.on('data', function(data) {
console.log('Received the following from pushtopic ---');
console.log(data);
});
});
}
Sails has a bootstrap.js file which lets you write anything you want to run before the server lifts.
I was able to subscribe to the push topic in a small function before the cb() in that file and it works, the server starts the REST API normally and it's still listening for events.

How to stop my web page rendering after socket io close

I have a NodeJS App with Socket Io integration. Now my web page and app both has been implemented but I am facing one issue during execution:
Below is my web page code:
<script>
$(document).ready(function(){
$("#batch")[0].reset();
var socket = io.connect('http://xx.xx.xxx.xx:xxxx',{'forceNew':true });
socket.on('message', function (data) {
var newtext = data;
document.batch.outputtext.value += newtext;
});
socket.on('end', function (data) {
socket.disconnect();
});
});
</script>
And my NodeJS App:
exec_script = function(resp) {
socket.on('connection', function (client) {
console.log('Connection Established');
client.on('disconnect', function () {
console.log('disconnected');
return;
});
var pyshell = new PythonShell('./test.py', options ={ mode: 'text', pythonOptions: ['-u'] });
pyshell.stdout.on('data', function(data) {
client.emit('message', data);
console.log(data);
});
pyshell.end(function(err) {
if (err) throw err;
console.log('End Script');
client.emit('end', 'end');
client.disconnect();
});
});
};
The issue I am facing is that when the Python scripts executes its output is send to browser while my browser status states "Waiting for xx.xx.xxx.xx" and in my FF I see the blue circle circling - that's fine - but even after the Python script has ended and socket disconnected explicitly I still see the browser status as "Waiting for xx.xx.xxx.xx browser title as Connecting with the blue circle rotating?
How can I close and end the connection successfully with the fact that I need the same page in the browser that is I would not navigate the user to some other page?
I tried by using response.end() but the issue I am facing is that if the request data was posted as URL form /today then calling response.end() changes the URL at browser side to http://xx.xx.xxx.xx:xxxx/today leading to a blank / error page which is what I a do not want in my case - the URL should remain as http://xx.xx.xxx.xx:xxxx?
Below is the method I am calling my exec_script method:
router.post('/', function(req, res) {
methods.process(req, res);
});
exports.process = function(req, resp) {
var bname = req.body['date'];
if(typeof req.body['date'] !== "undefined" && req.body['date'] !== null)
{
exec_script(req, resp);
}
};

Sails and Socket publishUpdate Can't Send data

I try learn Socket With sails but I have a problem with publishUpdate can't send data.
Let me show my code
User Module server Side
'subscribe': function(req,res,next){
User.find(function(err,users){
if (err) return next(err);
User.watch(req.socket);
User.subscribe(req.socket, users);
console.log('now user is subscribe in ',req.socket.id);
res.send(200);
});
}
app.js Client Side
(function(io){
// Connect To Socket
var socket = io.sails.connect();
if(typeof console !== 'undefined'){
console.log('Connecting to Sails.js ...');
}
socket.on('connect', function(){
// is undefined
console.log("This is handshake: ",socket.handshake)
// is undefined
console.log("This is from the connect: ", socket.id);
//console.log(socket);
// listen for message
socket.on('message', function(message){
console.log('New Message is Coming', message);
});
// Subscribe to the user model classroom and instance room
io.socket.get('/user/subscribe',function(){
//console.log('user now is subscribe ');
});
// log
console.log(
'Socket is now connected and globally accessible as `socket`.\n' +
'e.g. to send a GET request to Sails, try \n' +
'`socket.get("/", function (response) ' +
'{ console.log(response); })`'
);
});
})(
// In case you're wrapping socket.io to prevent pollution of the global namespace,
// you can replace `window.io` with your own `io` here:
window.io
);
in Session module server Side
user.online = true;
user.save(function(err,user){
//req.isSocket
var io = sails.io;
// emit to all sockets (aka publish)
// including yourself
I try this and work great and I revived message
//io.sockets.emit('message', {thisIs: 'USer Log in Id is ' + user.id});
User.publishUpdate(user.id,{
loggedIn : true,
id : user.id
});
console.log('User is signin', user.id);
// User Redirect To His Profile
if (user.admin){
res.redirect('/user/');
return;
}
res.redirect('/user/show/'+ user.id);
});
Now I try reload the server and show me in chrome browser
This is handshake: undefined
app.js:14 This is from the connect: undefined
app.js:32 Socket is now connected and globally accessible as socket.
e.g. to send a GET request to Sails, try
socket.get("/", function (response) { console.log(response); })
I remove publishUpdate and try emit.
I try this and work great and I revived message.
//io.sockets.emit('message', {thisIs: 'USer Log in Id is ' + user.id});

Socket.io emit callback not firing on server side?

My server emits events properly, but the emit callback never works. In the following, nothing is logged on my console:
Server:
io.sockets.emit('delete hint', {id: id}, function(data){
console.log('callback');
});
Client:
socket.on('delete hint', function(data){
// display a message before deleting
$('#' + data.id).fadeOut(function(){
$(this).remove();
});
});
I've also tried the client side code as function(data, fn) in case the callback needed to be included on the receiving function.
I'm using windows and my command prompt shows the following when socket.io is emitting the event:
websocket writing 5:::{"name":"delete hint", "args":[{"id":"1"}, null]}
I can't figure out what the problem is, what am I doing wrong?
A callback is executed on the sender computer when the receiver computer calls it
Have a look at this code:
Server:
io.sockets.on('connection', connectionFunc);
function connectionFunc (socket) {
socket.emit('delete hint', "data for client", callThis);
}
//this function is executed when client calls it
function callThis (dataFromClient){
console.log("Call back fired: " + dataFromClient);
}
Client:
socket.on('delete hint', function(data, callback) {
console.log("i received: "+ data);
// call back will fire only when u the next line runs
callback("the callThis function on server will run");
});
You can do this the opposite way.
You need to call the callback.
socket.on('delete hint', function(data, cb){
// display a message before deleting
$('#' + data.id).fadeOut(function(){
$(this).remove();
cb(null, 'done');
});
});

Resources