passport-google does not properly log out - passport.js

I have the following in my app.js
app.get('/logout', function(req, res){
req.logout();
console.log("Test "+req.isAuthenticated());
res.redirect('/');
});
Then I have the following in my index route...
console.log("IsAuth "+req.isAuthenticated());
if(req.isAuthenticated()){
console.log("Logged In");
}
else{
console.log("Logged Out");
}
But the console shows...
Test false
GET /logout 302 5ms - 90
IsAuth true
Logged In
GET / 304 91ms
What am I doing wrong here?

Looks like a side effect of using Oauth.Just how it works the lines are a little less clear.

The snapshot of code that you posted looks fine, and is more or less also the same I have on my github project for express 4 on
github-gpassport
that is working correctly in my browsers (chrome and safari).
That's a port to express 4 of an old express 3 version and I had some issue at the beginning configuring the session correctly.

Related

Rest api implementation with parameter using JetBrains WebStorm + node.js + express

First of all, i'm using JetBrains WebStorm and used to create the Node.js Express App project.
My modifications were at app.js
app.get('/api/restaurants', function(req, res) {
console.log("Parameter[0]", req.params.restaurant_id);
res.json({
'01010112D8139F13': '0ao123r1'
});
});
app.get('/api/restaurants/:id', function(req, res) {
console.log("Parameter[1]", req.params.restaurant_id);
res.json({
'message': 'worked?'
});
});
I'm using postman plugin at chrome to test my api and i can't access localhost:3000/api/restaurants?restaurant_id=01010112D8139F13 without being routed by router.route('/restaurants') instead of router.route('/restaurants/:restaurant_id')
At console i have:
GET /api/restaurants?id=01010112D8139F13 200 1.803 ms - 31
If anyone can help me, thanks in advance.
restaurant_id is not a query parameter but a variable part in your path. For example /restaurants/01010112 and /restaurants/1 are both handled by the same Web request handler because both fit on /restaurants/:restaurant_id pattern.
The restaurant specific endpoint need to be modified the following way:
app.get('/api/restaurants/:id', function(req, res) {
console.log("Parameter[1]", req.params.id);
res.json({
'message': 'worked?'
});
});
And use the following url on the console:
/api/restaurants/01010112D8139F13

nodejs+express+passort local 404 error when trying to logout

I am trying to add logout feature using passport local strategy.
I followed the solutions discussed here, here and here
I added a
a(href='/logout') logout
link in my index.jade file.
In my app.js I added the following:
app.get('/logout', function (req, res) {
console.log("trying to logout....")
req.session.destroy()
req.logout()
res.redirect('/signin');
});
But when I click the logout href It goes to my 404 page. In the browser url I see that it is attempting to go to:
localhost:3030/logout
I event added an empty logout.jade view but it makes no difference.
What am i doing wrong?
Also - I do not see the console.log("trying to logout...") message in my terminal... so it looks like it never reached the correct method.
Found answer thanks to #renatoargh pointing out that order of routes matter.
Somewhat annoyed that the passport docs don't mention this!!
BEFORE:
app.use(route.notFound404);
app.get('/logout', function (req, res) {
console.log("trying to logout....")
req.session.destroy()
req.logout()
res.redirect('/signin');
});
SOLUTION:
app.get('/logout', function (req, res) {
console.log("trying to logout....")
req.session.destroy()
req.logout()
res.redirect('/signin');
});
app.use(route.notFound404);

Browser is not getting redirected with res.sendFile()

In my Express app, when the admin sucessfully logs in, I want him to be sent to his dashboard page. So in the post function, on success, I redirect to admin/ which takes him to the next function
So I have:
adminRoutes.get('/', function(req, res){
console.log("/", path.join(__dirname, 'public/admin/index.html'));
res.sendFile(path.join(__dirname, 'public/admin/index.html'), {}, function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('Sent:');
}
});
});
But the problem is, nothing happens in my browser. It just stays on the browser page. It doesn't change to the new page I'm sending.
Why is it not working?
You should do a redirect not sendFile. sendFile is for telling the browser to download a specific file. Try:
res.redirect('public/admin');
Also, make sure this is registered in your routes. The route should then render the HTML.

URL gets changed on browser refresh ($routeProvider is used for client side routing)

I am using Angular for client and Nodejs (Express) for server side to build single page application. To support browser history for different view, I am using $routeProvider. It works well if I don't refresh the browser. But whenever I refresh the browser I notice that URL is changed which caused issue as that URL pattern doesn't exist at server. Following are more details.
Angular js router code:
$routeProvider.
when('/categoryview', {
templateUrl: 'templates/partials/app/categoryview/CategoryView.html',
controller: 'ApplicationController'
}).
when('/:categoryId/themes', {
templateUrl: 'templates/partials/app/themeview/ThemeView.html',
controller: 'ThemeViewController'
})
.otherwise({redirectTo: '/categoryview'});
URL in browser as application launched first time: http://localhost:3000/themelibrary#/categoryview
URL in browser on refresh: http://localhost:3000/categoryview#/categoryview
If you notice then you will found that the root URL "/themelibrary" is changed into "/categoryview" which caused issue as "/categoryview" is not supported by server. I also tried different version of Angularjs but not success.
Please help and let me know if need more code to explain this problem.
Edit: Added Nodejs router details
UI Routes:
module.exports = function(app, passport) {
// route for home page
app.get('/', function(req, res) {
res.redirect('/login');
});
//Route for login to present the login page back to user
app.get('/login', function(req, res) {
res.set({'content-type': 'text/html; charset=utf-8'})
res.render('login.ejs', {message: req.flash('loginMessage')})
});
//Route to get the username and password and authenticate
app.post('/authenticate', passport.authenticate('local-login', {
successRedirect: '/themelibrary', // redirect to the secure themelibrary section
failureRedirect: '/login', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
// route for default lending page
app.get('/themelibrary', isLoggedIn, function(req, res) {
var url= require('url');
console.log("themelibrary hash url >> " + url.hash);
res.charset = 'utf8';
res.set({'content-type': 'text/html; charset=utf-8'})
res.render('index.ejs', {
user: req.user
// get the user out of session and pass to template
});
});
// route middleware to make sure a user is logged in
function isLoggedIn(req, res, next) {
// if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next();
// if they aren't redirect them to the home page
res.redirect('/');
}
API Routes:
module.exports = function(app) {
app.get('/users/:id', userService.getUserById);
app.get('/users', userService.getAllUsers);
app.post('/themes', themeService.addTheme);
app.get('/themes/:id', themeService.getThemeById);
app.put('/themes/:id', themeService.updateTheme);
app.delete('/themes/:id', themeService.deleteTheme);
app.get('/themes', themeService.getThemes);
app.get('/resources/:code', languageResourceService.getLanguageResourceByCode);
app.get('/config', applicationConfigService.getApplicationConfig);
app.post('/keepalive', applicationConfigService.keepAlive);
app.get('/categories', categoryService.getAllCategories);
};
I would need to see your express routing rules to give a full answer, but since themelibrary is not a valid route according to the $routeProvider, your otherwise rule is being activated if you browse to this from within your application.
If you refresh the browser at this URL, $routeProvider is bypassed and the request is sent directly to your node.js instance where express will handle the route.
As for the hash route, that all depends if you have html5mode enabled or not as #david-spence pointed out.
Edit
The penny finally dropped on this one. If your angular app has loaded (and the only way for it to load is via the /themelibrary path), it will take over all of your routing, so any route changes via the application will be handled by ngRoute. That is to say, there will be no page reloads. Therefore, if the backend server is being hit by a request to /categoryview, some other part of the application is requesting a full page redirect via window.location.href or something similar.
In short, your routes are fine, some other part of the application is bypassing your routes and going straight back to the server (which it shouldn't).

How to log out from basicAuth (Express)

I'm trying to set up a web server using express. To access this server, users have to authenticate and for that, I use the basicAuth() middleware provided by Express. It works perfectly, except that I do not know how to log out once I logged in ! I have to close my browser to disconnect, but instead I would like to have a "disconnect" page which would redirect towards the "login" page (this one with the hideous form used to log in...).
Does anyone has an idea ?
Thanks per advance
PS : I apologize for my pathetic English :)
Express' basicAuth uses HTTP Basic Authentication whose implementation doesn't need HTML pages, cookies nor session ids. Its main drawbacks are its not secure and, our concern here, there is no mechanism in the spec for the server to instruct the browser to log out.
express.basicAuth() calls require(blah-blah/connect/lib/utils).unauthorized() which sends a 401 status with header 'WWW-Authenticate: Basic realm="..."'. The browser handles the authentication window and from then on sends a header like 'Authorization: Basic YmFzaWM6YmFzaWM=' which contains the username and password.
(express.basicAuth is not secure, especially over HTTP, because you can get the username:password with
new Buffer('YmFzaWM6YmFzaWM=' , 'base64').toString()
which gives basic:basic in this case.)
Our problem is the HTTP spec does not provide a way to stop that header being sent. A workaround for HTTPS is to redirect the user to a URL on the same domain having incorrect credentials.
The HTTP workaround I use for Express V3 can be used with app.use(express.basicAuth(...)). I find this easier to use than other solutions which require a call to middleware in every secured route, e.g. app.get('/secure', checkAuth, function (req, res) {...}).
Here is a working example.
var express = require('express'),
http = require('http'),
app = express();
app.use(express.favicon()); // prevent interference during test
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'winter is coming' }));
app.use(function (req, res, next) {
if (!req.session.authStatus || 'loggedOut' === req.session.authStatus) {
req.session.authStatus = 'loggingIn';
// cause Express to issue 401 status so browser asks for authentication
req.user = false;
req.remoteUser = false;
if (req.headers && req.headers.authorization) { delete req.headers.authorization; }
}
next();
});
app.use(express.basicAuth(function(user, pass, callback) {
callback(null, user === 'basic' && pass === 'basic');
}, '***** Enter user= basic & password= basic'));
app.use(function (req, res, next) {
req.session.authStatus = 'loggedIn';
next();
});
app.use(app.router);
app.get('/secure', function (req, res) {
res.send([
'You are on a secured page.',
'<br>',
'Refresh this page without having to log in again.',
'<br/>',
'Log out.'
].join(''));
});
app.get('/logout', function (req, res) {
delete req.session.authStatus;
res.send([
'You are now logged out.',
'<br/>',
'Return to the secure page. You will have to log in again.',
].join(''));
});
http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000. Point browser to route /secure');
});
P.S. Your English is excellent.
For express.js 4 and basicAuth, you can use this method:
app.get('/logout', function (req, res) {
res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return res.sendStatus(401);
});
Adding to wyllman, the 401 code is Unauthorized.
You can simply respond with res.status(401).send('Logged out')
or
app.get('/logout', function (req, res) {
res.status(401).send('Logged out')
//or res.status(401).end() if you don't want to send any message
});
I've confirmed that redirecting the user to a /logout page with an http code 401 and html with <a> element links to /login works.

Resources