Sails.js single instance of an authenticated user - node.js

I would like to only allow one instance of a user logged in. If I log in on this computer, and then go to another computer to login, the previous session should be destroyed. How can I do that? How can I access all sessions so I can destroy the right one or ensure that session's userID is unique? The only documentation I've seen for accessing the session regards req.session, which is only for the current session.

The typical way to implement this would be to save a user's session ID in the database, and whenever they log in, destroy the session whose ID was previously stored. Sails uses Connect's session store for session management. The session ID is exposed as req.sessionID, and the underlying session store is exposed as req.sessionStore. So, given the session store interface described in the Connect docs, you could do something like the following in your login action:
// Destroy the session from the previous login
req.sessionStore.destroy(loggedInUser.currentSessionId, function(err) {
if (err) {return res.serverError(err);}
// Save the session ID of the current login
User.update({id: loggedInUserId}, {currentSessionId: req.sessionID})
.exec(function(err) {
if (err) {return res.serverError(err);}
// Continue your login action...
});
});

Related

firebase.auth().currentUser returning null

In the html file that I have for the sign-in page, I perform the authentication using Firebase and on successful authentication, I redirect the given user to the homepage. When I call firebase.auth().currentUser in the express file, I use for rendering and routing pages, I get undefined or null for the current user.
Can anyone help me understand what the issue might be?
This is how I perform the authentication:
firebase
.auth()
.signInWithEmailAndPassword(temail, tpass)
.then(function(firebaseUser) {
window.location.href = "http://localhost:5000/homepage";
})
.catch(function(error) {
window.alert("incorrect pass");
});
This is the code that I have in my express file:
app.get("/homepage", (req, res) => {
var user = firebase.auth().currentUser;
console.log("USER IS " + user);
res.render("menu", { title: "Welcome" });
});
Backend code doesn't have a sense of "current user". When you sign in on the frontend, the current user is only known on that client. It isn't known on the backend. If you want the backend to know which user is signed in, the client will have to send an ID token to the backend for it to verify. The documentation for the Firebase Admin SDK is used for that on the backend. The client must send the ID token to in the request to your route, and the code handling that route must verify the token in order to know the user that made the request. From the documentation:
If your Firebase client app communicates with a custom backend server, you might need to identify the currently signed-in user on that server. To do so securely, after a successful sign-in, send the user's ID token to your server using HTTPS. Then, on the server, verify the integrity and authenticity of the ID token and retrieve the uid from it. You can use the uid transmitted in this way to securely identify the currently signed-in user on your server.
When the user lands on a new page, Firebase automatically restores their previous authentication state. But to do so, it may have to contact the server, which means that it may take a few moments. While Firebase is restoring the state, auth().currentUser will be null.
To ensure you get the correct authentication state, you should use an authentication state listener, as shown in the documentation on getting the current user:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});

prevent manipulation of JWT token in nodejs

I am trying to verify that somene if changed the JWT token from browser .The user should logout.
authorisedUser has some fields like username,id.
My code is working for only the case when any of this is changed and user is getting logged out.
But if i replaced this with another valid authorisedUser ,user is not logged out
So user A can user user B cookie and have access to his data.How should i change below code to verify it.
This is a light weight application so use of session or database is not there.
jwt.verify(req.cookies["authorisedUser"], "shhhhh", function (err, payload) {
if (err) {
res.redirect(db.env.application.logout_url+'?error=true');
//res.redirect(db.env.application.logout_url);
}
else{
//normal code}}

How do I track Stormpath authentication session with Stripe status?

I'm currently using express-stormpath for authentication with stormpath in my node.js application. I'm also using stripe. I'm attempting to figure out how to store sessions correctly. Here's what I plan to store in a user session:
session: {
sp_user: { //stormpath user details }
db_user: { //details from my DB }
stripe_expiraton: '234253843923' // unix timestamp
}
So on login I'm planning to create a session for the user with a 7-day expiration. On every API call express middleware will check to see if the stripe expiration date has arrived. If it has, or if there is no expiration date that means we need to redirect the user to the payment page. Otherwise will assume everything is normal and paid up and carry on.
Should I be storing session information this way? I'm not super experienced with session management.
What I'd recommend you do is store this information in your User Account's custom data store. Each Account in Stormpath lets you store any JSON information you want.
This is going to be a much better solution that storing your data in a session, as it might get wiped by the user at any time if it's only client-side.
Also: for Stripe, it doesn't really make sense to store a timestamp in most cases. The way you typically do billing is:
Collect the user's billing information.
Send it to Stripe using their JS APIs, you'll then get back a token.
Send the token to your Express app.
Use that token to create a Stripe Customer Object. This way you can bill the user in the future.
Store the Stripe Customer ID in your Stormpath Custom Data, this way you know how to bill the user later on!
With the above flow, you can automatically bill the user when you need to, instead of redirecting them to the payment page all the time. This also means you don't need to worry about session expiration, etc., and only need to redirect the user to the payment page if their card is expired or no longer valid.
Here's how to do it inside of a route:
app.post('/blah', stormpath.loginRequired, function(req, res, next) {
req.user.getCustomData(function(err, data) {
if (err) return next(err);
data.stripeCustomerId: 'xxx'
data.save(function(err) {
if (err) return next(err);
});
});
});
The above code will save your Stripe Customer ID inside your Stormpath account.
You can then retrieve this data at any time by saying:
req.user.getCustomData(function(err, data) {
if (err) return next(err);
data.stripeCustomerId; // this will be the value you've previously stored
});
Hope that helps =)

Understanding Passport.js - Tampering with the serializedUser

Am trying to wrap my head around passport.js, and am sure I am not using it correctly.
Particularly with the serializeUser() and deserializeUser() functions. My functions look similar to the two below. I am essentially pushing my database user._id into the session (which I don't like to do), and can view it easily in the browser with a cookie viewer.
passport.serializeUser(function(user, done) {
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
done(null, id);
});
So, for every secure request, I run an isAuthenticated() function which checks that the user is Authenticated with Passport, and then I use the deserialized ID in req.user to perform various CRUD operations on the database.
What I am wondering is what would stop an authenticated user from replacing their own user._id with someone else's user._id in the session, and gaining access to all these CRUD db operations for a different user.
Does passport have some sort of hashing algorithm to check the serialized data hasn't been tampered with?
Should I not be using the returned ID for my database CRUD operations?
Is there another way to avoid sending the user._id to the browser?
This is the session middleware which makes sure that session data is not tampered, you just need to provide the secret option which will be used to sign it.
From express session middleware documentation (https://github.com/expressjs/session)
secret - session cookie is signed with this secret to prevent tampering.
Ex. app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
According to the passport docs(http://passportjs.org/guide/configure/):
The serialization and deserialization logic is supplied by the
application, allowing the application to choose an appropriate
database and/or object mapper, without imposition by the
authentication layer.
So, you have to implement serializeUser() and deserializeUser() methods. Serialize method will return the identity information to recover the user on future requests. And that identity information will be saved in the session. Deserialize method should be able to identify the user based on that identity information. Whether you use database id, some randomly generated string, UUID or something similar is up to you and your security requirements.

How do i destroy session of a particular user using Id?

How to destroy the session of a particular user using his/her user_id ?
I have an events like when admin assign role to a normal user then, if the normal user is logged in, I have to destroy the session of the normal user.
Any help would be appreciated.
Thanks
The session of the logged in user has an id that you can save after successful login: req.session.id. Then you can retrieve that user's session from the memory store at any time and destroy it using:
sessionStore = express.session.MemoryStore();
sessionStore.get(id, function(err, sess) {
sess.destroy (function (err) {
});
});

Resources