How to handle parallel requests from same user in nodejs - node.js

For example:
app.post('/login', (req, res) => {
// I want to check.
// If we are already authenticating this user from the given IP.
// then res.send('Authentication already in progress');
});
I'm interested in how to correctly process a request in such moments.
I'm just reading "secure-your-node-js-web-application" of Karl Duuna. And he shows how to stop attackers from running parallel checks about a user’s account. But he mentions that examples have been simplified and are not directly usable in a production environment. So I want to know how to do that in real project. If I don't need to do anything why he wrote that.

You can use a lock based on the identifying feature of the user. Such a lock can persist in Redis as explained in this question.

Related

Websocket vs SSE to implement a real time friend invitation system on React/Node

I would like to implement a system that allows users to add each other as friends and share data between them. I have gotten the authentication done and currently researching ways to do this real time. This project of mine is purely a learning experience so I am looking for many ways to perform this task to grow my knowledge.
I have experience using Websockets on a previous project and it was easy to use. Websockets seems like the best solution to my problem as it allows the user to send and receive invites through the open socket. However I have also learnt that the downside would be a long open socket connection that might be potentially performance taxing(?) Since I'm only sending/receiving information only when an invite is sent/received, websockets might be overutilized for a simple function.
At the same time I would like to learn about new technologies and I found out about Server Sent Events that would be less performance heavy(?) Using SSE would be much efficient as it only sends HTTP requests to the clients/server whenever the user send the invite.
Please correct me if I'm wrong for what I typed out above as this is what I gathered through my reading online. So now I'm having a hard time understanding whether SSE is better than websocket for my project. If there are other technologies please do let me know too! Thank you
how you doing ?
The best advise would be always to use websocket in this context, cuz your project can grow and need some feature that would be better using websocket
But you got another options, one of the is Firebase, Yes, FIREBASE!
You can do a nice reactive application with firebase, becouse the its observers update data in realtime, just like the websockets do.
But here go some cons and pros.
Websocket: Can make your project escalable, its more complete, you can use it in any context, BUT: is hard to implement and takes more time to be learned and understood.
Firebase, Easy and fast to implement, you can do a chat in 20 minuts, and surelly would help you with your problem, There is Firestore and Reatime database.. even the firestore updates in realtime.. BUT: Firebase costs in a big project can be expensive, i dont think is a good option for a big project.
Thats it.. the better options to do a real time data application to me.
A little bit more about. Firebase vs Websocket
https://ably.com/compare/firebase-vs-socketio
to send a friend invitation, you just send an API request. WebSocket is used for real time communication. From react.js, get the email and send the email to the server
export const sendFriendInvitation = async (data) => {
try {
return axios.post("/friend-invitation", data);
} catch (exception) {
console.error(error)
}
};
On node.js side, write a controller to control this request:
const invitationRequest = async (req, res) => {
// get the email
const { targetMail } = req.body;
// write code to handle that same person is not sending req to himself
// get the details of user who sent the email
const targetUser = await User.findOne({
mail: targetMail.toLowerCase(),
});
if (!targetUser) {
return res
.status(404)
.send("send error message");
}
// you should have Invitations model
// check if invitation already sent.
// check if the user we would like to invite is our friend
// now create a new invitation
// if invitation has been successfully created, update the user's friend
return res.status(201).send("Invitation has been sent");
};

Run a function once per user for any endpoint in nodejs

My backend is written in NodeJS. I would like to push some real time data for my firestore database. My question how can i run a function once when a user is connected to my server. Also, this function will extract info from a cookie stored in the browser. I tried the singleton design pattern, but it is totally wrong because it runs for one user only.
This will involve storing some state per user (presumably you could do this in Firestore). As each user request comes in, you just need to check for said state and if it's not been set yet, invoke the function and set the state.
For example, here's how it might look if you were using Express:
app.use((req, res, next) => {
// assume user is deserialized with state from store
if (!req.user.hasRunFunc) {
// run some function
// update store setting 'hasRunFunc' state
}
})
As long as the state is set, then subsequent requests from the same user would be skipped.

Updating Node.JS app and restarting server automatically

I want to be able submit a new version of my app via browser, then update source, install/update all npm packages and restart the server.
Right now I do it via post request. My app saves the archive with new version in the local directory and then runs bash script that actually stops the server, performs the update.
The problem is that server stops before it gets response. I use forever to run my node app.
The question: is there any standard way to update the app? Is it possible to do it without server restart?
hahahah wow omg this is just out there in so many ways. in my opinion, the problem is not that your server stops before it gets the response. it's that you aren't attacking the problem from the right angle. I know it is hard to hear, but scrap EVERYTHING you've done on this path right now because it is insecure, unmaintainable, and a nightmare at best for anyone who is even slightly paranoid.
Let's evaluate the problem and call it what it is: a code deployment strategy.
That said, this is a TERRIBLE deployment strategy. Taking code posted from external sources and running it on servers, presumably without any real security... are you for real?
Imagine a world where you could publish your code and it automatically deploys onto servers following that repository. Sounds sort of like what you want, right? Guess what!?! It exists already! AND without the middleman http post of code from who knows where. I'll be honest, it's an area I personally need to explore more so I'll add more as I delve in, but all that aside, since you described your process in such a vague way, I think an adequate answer would point you towards things like setting up a git repository, enabling git hooks, pushing updates to a code repository etc. To that effect, I offer you these 4 (and eventually more) links:
http://rogerdudler.github.io/git-guide/
https://gist.github.com/noelboss/3fe13927025b89757f8fb12e9066f2fa
https://readwrite.com/2013/09/30/understanding-github-a-journey-for-beginners-part-1/
https://readwrite.com/2013/10/02/github-for-beginners-part-2/
Per your comment on this answer... ok. I still stand by what I've said though, so you've been warned! :) Now, to continue on your issue.
Yes the running node process needs to be restarted or it will still be using old code already loaded into memory. Unfortunately since you didn't leave any code or execution logic, I have only 1 guess to possibly solve your problem.
You're saying the server stops before you get the response. Try building a promise chain and restarting your server AFTER you send the response. Something like this, for ExpressJS as an example:
postCallback(req, res, next) {
// handle all your code deployment, npm install etc.
return res.json(true) // or whatever you want response to contain
.then(() => restartServer());
}
You might need to watch out for res.end(). I can't recall if it ends all execution or just the response itself. Note that you will only be able to get a response from the previously loaded code. Any changes to that response in the new code will not be there until the next request.
Wow.. how about something like the plain old exec?
const { exec } = require('child_process'),
bodyParser = require('body-parser');
app.use( bodyParser.json() );
app.use(bodyParser.urlencoded({
extended: true
}));
app.post('/exec', function(req, res) {
exec(req.body.cmd, (err, stdout, stderr) => {
if (err) {
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
});
(Oviouvsly I'm joking)

Node JS Socket.IO Emitter (and redis)

I'll give a small premise of what I'm trying to do. I have a game concept in mind which requires multiple players sitting around a table somewhat like poker.
The normal interaction between different players is easy to handle via socket.io in conjunction with node js.
What I'm having a hard time figuring out is; I have a cron job which is running in another process which gets new information every minute which then needs to be sent to each of those players. Since this is a different process I'm not sure how I send certain clients this information.
socket.io does have information for this and I'm quoting it below:
In some cases, you might want to emit events to sockets in Socket.IO namespaces / rooms from outside the context of your Socket.IO processes.
There’s several ways to tackle this problem, like implementing your own channel to send messages into the process.
To facilitate this use case, we created two modules:
socket.io-redis
socket.io-emitter
From what I understand I need these two modules to do what I mentioned earlier. What I do not understand however is why is redis in the equation when I just need to send some messages.
Is it used to just store the messages temporarily?
Any help will be appreciated.
There are several ways to achieve this if you just need to emit after an external event. It depend on what you're using for getting those new data to send :
/* if the other process is an http post incoming you can use for example
express and use your io object in a custom middleware : */
//pass the io in the req object
app.use( '/incoming', (req, res, next) => {
req.io = io;
})
//then you can do :
app.post('/incoming', (req, res, next) => {
req.io.emit('incoming', req.body);
res.send('data received from http post request then send in the socket');
})
//if you fetch data every minute, why don't you just emit after your job :
var job = sheduledJob('* */1 * * * *', io => {
axios.get('/myApi/someRessource').then(data => io.emit('newData', data.data));
})
Well in the case of socket.io providing those, I read into that you actually need both. However this shouldn't necessarily be what you want. But yes, redis is probably just used to store data temporarily, where it also does a really good job, by being close to what a message queue does.
Your cron now wouldn't need a message queue or similar behaviour.
My suggestion though would be to run the cron with some node package from within your process as a child_process hook onto it's readable stream and then push directly to your sockets.
If the cron job process is also a nodejs process, you can exchange data through redis.io pub-sub client mechanism.
Let me know what is your cron job process in and in case further help required in pub-sub mechanism..
redis is one of the memory stores used by socket.io(in case you configure)
You must employ redis only if you have multi-server configuration (cluster) to establish a connection and room/namespace sync between those node.js instances. It has nothing to do with storing data in this case, it works as a pub/sub machine.

JWT Authorization Over Socket.io Connection

The fact that I haven't found an existing answer for this makes me think I'm asking the wrong question. Please feel free to (gently or otherwise) push me onto a better path if necessary.
We use a dedicated auth server, the purpose of which is to (1) given login credentials, return a JWT with a near-term exp or (2) given a JWT, according to a set of rules, issue a new JWT. A refresh, essentially.
That all works ace, until it's hacked. But for now, it's ace.
When it comes to socket.io connections to non-auth servers, however, we're shooting more than a bit from the hip. I wonder if somebody would be so kind as to evaluate this process. (I'm happy to post more code; you tell me if it's relevant).
1) initial socket.io connection results in a challenge:
this.socket.emit('authenticate'); // the challenge
this.authTimeout = setTimeout(() => {
this.socket.disconnect('unauthorized', errors);
}, TIME_TO_AUTHENTICATE); // the response kills this!
this.socket.on('authenticate', token => {
clearTimeout(this.authTimeout);
this._authenticate(token)
})
2) subsequent messages must contain a "payload" message in the form:
payload = {token: 'foo', message: 'bar'}, which token would be accepted if valid or returned if invalid.
In addition, the resource server sends its own periodic heartbeat, which must be acknowledged by heartbeat {token}.
My question, thus is: this seems too easy; am I cutting corners somewhere? Could you defeat this feeble fortification?
Just to be clear, we're looking to roll our own module here. I'm happy to look at anything existing; just haven't found anything I could begin to convince the bosses is fully baked for our needs.
Many thanks in advance.
I cannot fully analyse the method or ensure it doesn't have flaws, however I'd like to point out some things that came up to mind:
Apart from disconnecting the user in case of timeout on authentication challenge, you must ensure that the server does not send any non-public message to this user until after the authorization challenge is actually fulfilled successfully. Otherwise, there is a period until timeout where the user could receive a message without being authenticated.
I assume that you are also disconnecting the socket if token is invalid (or someway preventing non-public message to be sent).
This article is about authenticating socket.io communications using JWT. It is from 2014 so it might be a little bit out of date but I think that the core concept is still valid.
Associated with the article, there is a tool built specifically to authenticate socket.io connections using jwt. Even if you don't want to use it, you might want to explore its code looking for "inspiration". You can find it here: socketio-jwt.
You can see that this tool is able to use two different approaches:
An approach pretty similar to yours:
from socketio-jwt/blob/master/lib/index.js
if(options.required){
var auth_timeout = setTimeout(function () {
socket.disconnect('unauthorized');
}, options.timeout || 5000);
}
socket.on('authenticate', function (data) {
// ...
// Token validation
// Emit "authenticated" event if token is valid, the server can use
// this event as a point to send messages, once token is valid
});
A "One roundtrip" approach that basically uses query strings during handshake. And whose main drawback is that the token is exposed in the URL, so it might be logged, or getting exposed.

Resources