How do I determine which user has logged in in an express js application? I want to determine who is sending the request in my server program.
MeanJS stack
You can use req.user
exports.some_method = function(req, res) {
var user = req.user;
//do something
};
But you have to use users.requiresLogin to have persisted user
app.route('/model/:modelId').get(users.requiresLogin, my_controller.some_method)
It's implementation is pretty simple
exports.requiresLogin = function(req, res, next) {
if (!req.isAuthenticated()) {
return res.status(401).send({
message: 'User is not logged in'
});
}
next();
};
It's session based implementation indeed, but still good. That's it
Pure expressJS
You must use middleware that would detect current user by its cookie
It's more complicated indeed, and you have to write own implementation
But there are plenty of plugins, like passport, that would validate user by your fields. Also can serialize into req.user and vice versa
But i would strongly recommend to checkout MeanJS stack implementation, it's pretty easy to understand. As the name implies, it's MongoExpressAngularNode, so it's express based stack.
More
It depends on what kind of auth schema you are using, if it's REST, then you have to pass token in all requests to server, so that server checks db and get's user with corresponding token. If it's sessions based, then you can simple use any session based plugins. But the idea is same, when signing in, serialize user to session table, set cookie, when receiving request take cookie from requester, deserialize from session table, you got user now
Related
I will explain more here so that it's clear what I am trying to do. I am creating a web application using Express.js and Node.js. I am trying to create a user profile at this moment. I have seen different way to render the user profile some websites goes like : Quora : https://www.quora.com/profile/************, Stackoverflow : https://stackoverflow.com/users/4056534/sandip-subedi and Facebook/Many other www.facebook.com/username.
I want to make something like what Facebook is doing. www.MYURL.com/USERNAME. How do I achieve that ? I know how to handle GET request and POST requests. There is a problem here because I already have more than 40 GET/POST request with different URL names. Since all of them are coming from www.MYURL.com/DOSOMETHING I couldn't figure out right way to filter if it is a user's profile or other URL. If I was doing something like www.MYURL.com/user/USERNAME it will be easy because I already know I am dealing with user at this moment.
You can create a router to namespace endpoints:
let router = express.Router()
router.get("/:username", (req, res, next) => {
// req.params will have the URL's username parameter
console.log("Request for user with username", req.params.username)
})
app.use("/user", router)
This mounts the username route on the user route: /user/[username]
https://expressjs.com/en/guide/routing.html
I've been working on this for the past day and can't seem to figure it out. I am using this Passport-Soundcloud to implement a soundcloud authentication. However what I don't understand is how I can get, and pass an authentication token to a front-end button push to like a sound.
My front-end code looks like:
function allowLike(){
$('.queueTrack').off('click').on('click', function(user){
console.log('clicked');
SC.put('/me/favorites/' + 21928809);
consol.log('sound liked')
});
};
Whenever I try to login through my app using the /login route, it works as expected and redirects me to my homepage. The problem is that I don't know how to get the oauth token from the passport-soundcloud so I can implement it into the front-end click event.
My routes followed the passport-soundcloud instructions and seem to work, but I can't figure out how to get the oauth token...
Any ideas? I'm totally lost on this.
So, I'm not familiar with the specific details of the soundcloud api. But if it follows the basic patterns of popular oauth apis. Then you'll want to do something like this.
User arrives at your site without a cookie
they authorize your app using oauth
when the user is redirected back to your app, SoundCloud will give you an access key for this user. Store this value, in a database or a cache or in memory. But most importantly, you must create a cookie on that users browser. So that when they return you can lookup the access key again.
When the user clicks like, lookup the accesskey on the backend and hit SoundCloud api with that token.
In the initial oauth flow....
function(accessToken, refreshToken, profile, done) {
User.findOrCreate({
soundcloudId: profile.id,
token: accessToken // <--- store the token!
}, function (err, user) {
return done(err, user);
});
}
then when they click like
app.put('/me/favorites/12345' function(req, res) {
var id = req.user.id; // <--- passport and connect session saved the user id for you
// lookup the token in your database
// use the token to hit the soundcloud api
})
I hope this make some kind of sense. This is completely untested pseudo code.
I'm very new to learning Node and Express, and I'm still trying to wrap my head around the code flow with express. Suppose we have code that looks like this in a session.js:
app.post('/session', notLoggedIn, function(req, res) {
User.findOne({
username: req.body.username,
password: req.body.password
}, function (err, user) {
if (err) {
return next(err);
}
if (user) {
req.session.user = user;
res.redirect('/users');
} else {
res.redirect('/session/new');
}
});
});
Assuming the User is a required mongo schema. What I find strange is the session.user assignment:
req.session.user = user;
Since the req variable will be out of scope after the redirect, but we're obviously doing this to persist the user data, I'm left with figuring out which of the following scenarios describe what is happening. Either (A) the argument that's being assigned to the req parameter (when the callback is called) is stored/somewhere still on the stack, (B) the session is stored/on the stack and being assigned to a new req object before it's passed in to the callback, or (C) the same as B, but on the user field (seems unlikely and maybe contrived on my part).
There's an overall session data structure that stores all session info for all users (like a global, but it could also be in a database - just something that is persistent at least across connections). Each client's session data uses one unique key to index into the session store to get the session data for that client.
Part of establishing a session for a given browser client is creating a unique client key (which will usually be stored in a cookie) that becomes the index into the global session object.
On an incoming http request, Express middleware that supports the session checks a particular client cookie and if that particular cookie is found on the http request and is found in the global session object/database, then it adds that session's stored info to the request object for the http request handler to later use.
So, here's a typical sequence:
Incoming HTTP request.
Middleware checks for session cookie.
If session cookie not there, then create one and, in the process created a unique id to identify this http client.
In the persistent session store, initialize the session for this new client.
If session cookie is there, then look in the session store for the session data for this client and add that data to the request object.
End of session middleware processing
Later on in the Express processing of this http request, it gets to a matching request handler. The session data from the session store for this particular http client is already attached to the request object and available for the request handler to use.
I think the accepted answer misses one crucial detail, which was surfaced by #jpaddison3: "Express-session hooks res.end() to see when the request is done and then it updates the session store if needed."
Basically, when you add the expression-session middleware, it wraps res.end() so that the new session information is saved just before the stream is closed.
I am using passport-local-mongoose and trying to setup a simple working example using the login example in the repository. But I'm running into problems and I get an error message saying "Error: failed to serialize user into session".
I have reproduced the problem in a gist. (To run the gist, you will need to replace the mongodb server IP and database name in the user.js file and do a POST to the /register endpoint with username and password values.)
In it you will see the endpoints '/setval' and '/getval' which set values in the session and retrieves it, showing that session support is working. The endpoint '/authtest' gives an Unauthorized response, even after doing a POST to '/login'. The endpoint '/authdebug' gives more information - the error mentioned above.
Anyone have any ideas on what is going on? I'm running out of things to try.
I think that passport.authenticate should only be used on routes which are actually used for authenticating the user; in your case, that would be the /login route.
For routes for which you want to make sure a user has previously authenticated, like /authtest, you need a middleware which checks if a user is authenticated:
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect('/login'); // or your login page
}
// and
app.get('/authtest', ensureAuthenticated, function(req, res) {
...
});
An alternative for that middleware would be connect-ensure-login.
I'm having a problem with Express under Node.js. I'm trying to use sessions to store auth details when a user logs in. The problem I'm having is that once one user is logged in, any other visitors are also logged in under the same user, even if they are on a seperate machine on a seperate network.
It appears to me that it's working more like an application data store than a session store. Am I doing something wrong? Seems to me like I'm doing something stupid somewhere!
I'm using this code in app.configure:
app.use(express.cookieParser());
app.use(express.session({secret: 'supersecretkeygoeshere'}));
And I'm getting and setting my session variables like this:
var user = express.session.userId;
Cheers,
Nathan
That's not how you use sessions, use the session var on a request object:
app.get('/login', function(req, res){
user = loadUser(req.body.username, req.body.password)
req.session.userId = user.id
})
see docs:
http://expressjs.com/guide.html#session-support
Hope that helps :D