Unable to get simple passportjs with mongoose working - javascript

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.

Related

GET vs POST for fetching HTML page

Am able to fetch html page properly using postman GET But getting error while fetching html page using POST using postman
Error details :
404 Not Found404 Not Found
We have frontend code on html/JS and backend code on nodeJS
This can happen for so many reasons. Check your imports, routes and request url.
Though it is not the way to get your html through POST method. Using GET method is the right way.
const express = require("express");
const router = express.Router();
router.post("/", (req, res, next) => {
res.render("index", { title: "Express" });
console.log(req);
});
module.exports = router;
It is good if fetch data using GET method only and if it is giving 404 Error then it means you might have not created any route with POST method. Same route with different method treat as different route like
1) GET http://example.com/fetch
2) POST http://example.com/fetch
are 2 different routes. You need to define each separately
I believe that for fetching data, GET is the preferred method and POST should be used to update server-side resources, not to retrieve them. If POST is returning 404, You may not have a POST route configured, or POST access may be disabled by itself through your server's configuration.
Usually the "GET" method is used when requesting the an html page, for example all the browsers, uses "GET" for requesting the landing page of any url.
Post usually is used to send data and logging in.
You need to create a route for POST requests to get the HTML.
I'm assuming that you must be using some kinda framework router like express-router to route your pages. In your router code, you would be having something like
app.get('/myHtmlPage', function(req, res) {
// some code
})
so you're getting your page back for making GET requests. You need to create a similar route like
app.post('/myHtmlPage', function(req, res) {
// some code
})
to get the same page for POST requests.

Soundcloud Login with NodeJS and Liking Sounds Issue - 401 Unauthorized

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.

Loading an Angular App from the Backend

I want to check if a user is authenticated from the backend BEFORE anything else has loaded in my angular app, so that no source code has loaded. The initial request to be sent to the back end will be to see whether the user is authenticated. If so, the app will be loaded.
Alternatively, I would like to know how I could have my backend check authentication when the page is requested, and send different content depending on whether the user is logged in or not.
How can I best accomplish this?
app.use(function(req, res, next) {
console.log(req);
next();
});
app.all('*', function(req, res, next) {
console.log(req);
res.send('hey');
})
Why don't these work in my node app?
If you're using a render engine like jade. In your jade template that loads you can embed angular and embed the ng-view on said jade template.
So you have the server handle auth using a jade template tk render your open/public page and then authenticate. Once they pass your Auth test redirect the page to the jade template which has the angular on it. jade will then render the page, once the page loads angular gets called and your angular app will take over the page.
Just be careful if you use URIs that overlap on your server routes and your angular template URIs as they will trigger any middleware on those routes during the ajax call.
I give a very helpful tutorial about authentication with token; in general the idea is use a interceptor that check if the user was authenticated, in case that the user was not authenticate redirect to default or login page
You need to authenticate your user and check his authorization somehow. For example, if you use session-based authentication (quite similar to the way PHP does sessions), you might have a /login site that renders the user's login page. With a custom expressjs middleware you can then redirect unauthorized users or reply with a 401 Unauthorized/403 Forbidden.
app.use(require('cookie-parser')());
app.use(require('express-session')());
// ...
app.post('/login', function (req, res, next) {
if (credentialsAreOK(req) {
req.session.authorized = true;
res.redirect('/pageAfterLogin');
} else {
res.send(401);
}
};
var checkAuthorization = function (req, res, next) {
if (req.session && req.session.authorized) {
return next();
} else {
res.redirect('/login');
// or return res.send(401);
}
};
app.get('/protectedSite', checkAuthorization);
// or
app.get('/protectedSite', checkAuthorization, protectedSiteHandler);
You could have your backend check authentication when the page is requested, and send different content depending on whether the user is logged in or not.
The other way is to resolve a service in your route config which checks authentication before the route is resolved. https://docs.angularjs.org/api/ngRoute/provider/$routeProvider

Determine the sender of http request

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

JavaScript / Node Syntax Misunderstanding

I'm working on a Node.js app. Everytime I think I understand JavaScript, a curve ball is thrown at me that I don't understand. Currently, I'm trying to use passport.js to authenticate a user. I have the following code (which works):
passport.authenticate('google')(req, res, function() {
// TODO: Handle a user not authenticating
// This is the happy path. It will always execute. However, it should only execute if a user authenticated with google.
logger.info('user authenticated');
res.redirect(307, '/auth-confirm');
});
My challenge is, I need to detect when a user fails to authenticate with Google. If they succeed, I need to get the access token. However, I do not know how to do either of these because I do not understand the syntax of this call. Specifically, I don't understand what (req, res, function() {...}) is.
Is that line saying that passport.authenticate returns a function. So, req, res, and function() { ... } are passed as parameters to the function that passport.authenticate returns? If that's the case, I still don't know how to get the access token returned by google.

Categories