I'm working on a Google Chrome extension with a popup, in which I load a page from a node.js + express.js server. The page I load changes depending on the status of the req.session.user in this way:
app.get('/', function(req, res){
if(req.session.user){
res.render(__dirname + '/pages/base.jade', {});
}
else{
res.render(__dirname + '/pages/login_register.jade', {});
}
});
If req.session.user is null I send a page in which the user can do the login or register. If he/she does a login, this is what happens in the server:
app.post('/login', function(req, res){
var user = {};
user.username = req.body.username;
user.password = req.body.password;
checkLogin(user, function(foundUser){
//login correct
console.log("login!");
req.session.user = foundUser;
res.render(__dirname + '/pages/base.jade', {
});
});
});
So if the user logs in correctly req.session.user should be set with the credentials of the current user. The problem is that once I log in and then close the popup of the Chrome extension, whenever I reopen it I still receive the login page.
My question is: does the popup supports session storage in the express.js server? If yes, then there is something wrong with my code, can anyone point out what am I doing wrong? Thanks.
EDIT:
This is how I setup the server:
var app = express.createServer(
express.logger(),
express.cookieParser(),
express.session({ secret: 'keyboard cat' })
);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
I might be doing something redundant here, since I still don't have a deep understanding of how that works.
The problem is how you have set up your server - you're using the cookieParser and session middlewares twice:
var app = express.createServer(
express.logger(),
express.cookieParser(),
express.session({ secret: 'keyboard cat' })
);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
You should only use either middlewares as parameters to createServer, or use, so:
var app = express.createServer();
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
Popup page probably reloads every time you open it. You should create a backgroundpage for your extension where you could store/manage sessions. Then you can communicate from popup to backgroundpage passing messages docs. Using messaging you can send login data to backgroundpage and also ask whether user has already logged in.
Related
I'm using PassportJS and NodeJS as backend for a website server. It uses the Passport-Local strategy. I develop the website in a MacOSX environment.
The server serves pages for information about our company and our commercial product.
It also serves help files (HTML web help) generated using Help and Manual.
The software that we sell runs on Windows and is programmed in Delphi VCL. We set it up so that it will redirect to our web help when pressing F1 using contextual ids like such :
procedure MyForm.OnHelp(blabla)
begin
ShellExecute( blabla, www.mywebsite.com/secure/help?contextid=202383)
end
All paths in www.mywebsite.com/secure are secure, and will require authentication with the passport.js middleware.
This is the relevant routing / passport configuration.
// CHECK AUTH METHOD
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
req.session.target = req.originalUrl;
req.session.save(function (err) {
res.redirect('/login')
});
}
// PASSPORT LOGIN STRATEGY
passport.use(
new passportLocal.Strategy({
usernameField: "username",
passwordField: "password"
},
function (email, password, done) {
if (!email) {
return done(null, false);
}
if (!password) {
return done(null, false);
}
if (password.toLowerCase() === 'ASTUPIDPASSWORD') {
return done(null, {email: email});
} else {
return done(null, false);
}
}
));
// PASSPORT SERIALIZE
passport.serializeUser(function (user, done) {
done(null, user.email);
});
// PASSPORT DESERIALIZE
passport.deserializeUser(function (email, done) {
done(null, {email: email});
});
// OTHER AMAZING ROUTES
router.use('/secure', ensureAuthenticated);
router.get('/secure/help', function (req, res) {
res.redirect('/secure/help/index.html');
});
This is the express configuration
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var compression = require('compression');
var fs = require('fs');
var passport = require('passport');
var session = require('express-session');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'client', 'views'));
app.set('view engine', 'jade');
app.use(compression());
app.use(favicon(__dirname + '/client/images/favicon.png'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true})); //
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'client')));
app.use(express.static(path.join(__dirname, 'client')));
app.use(session({
saveUninitialized : true,
resave : false,///
secret: 'adamngoodsecret
}));
app.use(passport.initialize());
app.use(passport.session());
var routes = require('./routes/index');
app.use('/', routes);
When I develop in the MacOSX environment, I will login once. Then, I will be able to return to the secure zone because I guess I will have a cookie set up, regardless if I'm using safari or chrome.
Though, when I test it in a Windows environment, the problem occurs.
I open the broswer, type in www.mywebsite.com/secure/help?blabla
I am asked for login. OK
I enter login. OK
I am redirected to the initial requested url. OK
I close the tab WITHOUT CLOSING THE BROWSER. OK
I request the www.mywebsite.com/secure/help?blabla URL. OK
I can access the resource. OK
I close the browser. OK.
I open a new broser window. OK.
I request the www.mywebsite.com/secure/help?blabla. OK
I get asked for credentials. FAIL
So, whenever I close the browser window (Safari, Chrome) in Windows 10 environment, I get asked for the credentials again.
In MacOSX, even if I close the browser, I do not get asked the credentials again.
It is very unconvenient for my users to have to enter their credentials each time on the Windows environment.
Can anyone point me in the right direction in order to solve this? It seems the cookies in the Windows 10 environment are reset whenever the browser window is closed, though I'm not sure.
Thanks.
Is it possible to do basic auth in Node.js just like in Apache?
http://doc.norang.ca/apache-basic-auth.html
I know that if using Express or Connect I can add middle-ware functionality and do user verification, but I'm trying to restrict the whole area (I don't need to authenticate users from a database just a couple of defined users) - I'm using Ubuntu.
https://github.com/kaero/node-http-digest
That's something I can do, but I'm not sure if "exposing" or directly writing the user and password in the code is secure enough.
Many thanks.
Passport provides a clean mechanism to implement basic auth. I use it in my Node.js Express app to protect both my Angularjs-based UI as well as my RESTful API. To get passport up and running in your app do the following:
npm install passport
npm install passport-http (contains "BasicStrategy" object for basic auth)
Open up your app.js and add the following:
var passport = require('passport')
var BasicStrategy = require('passport-http').BasicStrategy
passport.use(new BasicStrategy(
function(username, password, done) {
if (username.valueOf() === 'yourusername' &&
password.valueOf() === 'yourpassword')
return done(null, true);
else
return done(null, false);
}
));
// Express-specific configuration section
// *IMPORTANT*
// Note the order of WHERE passport is initialized
// in the configure section--it will throw an error
// if app.use(passport.initialize()) is called after
// app.use(app.router)
app.configure(function(){
app.use(express.cookieParser());
app.use(express.session({secret:'123abc',key:'express.sid'}));
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('view options', {
layout: false
});
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.use(passport.initialize());
app.use(app.router);
app.use(logger);
});
// Routes
app.get('/', passport.authenticate('basic', { session: false }), routes.index);
app.get('/partials/:name', routes.partials);
// JSON API
app.get('/api/posts', passport.authenticate('basic', { session: false }), api.posts);
app.get('/api/post/:id', passport.authenticate('basic', { session: false }), api.post)
// --Repeat for every API call you want to protect with basic auth--
app.get('*', passport.authenticate('basic', { session: false }), routes.index);
Put this
app.use(express.basicAuth(function(user, pass) {
return user === 'test' && pass === 'test';
}));
before the line to
app.use(app.router);
to protect all routes with http basic auth
Have a look at:
user authentication libraries for node.js?
It does not answer your question 100% - but maybe it helps.
I think good choice could be http-auth module
// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area.",
file: __dirname + "/../data/users.htpasswd" // gevorg:gpass, Sarah:testpass ...
});
// Application setup.
var app = express();
app.use(auth.connect(basic));
// Setup route.
app.get('/', function(req, res){
res.send("Hello from express - " + req.user + "!");
});
When user login, i am storing data in session like this :
req.session.user = userData;
And it is working fine but when i restart in nodejs, the session is null. Then user need to login again.
I want to create a file based storage for session.But after a lot of search, i got the way to store data in database but i dont want to store session data in database. I want to store data in file.
Is there a nodejs module to store the session data in file?
You can use session-file-store. can refer below working example.
var express = require('express');
var app = express();
var session = require('express-session');
var FileStore = require('session-file-store')(session);
app.use(session({ secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new FileStore,
cookie: { maxAge: 3600000,secure: false, httpOnly: true }
})
);
app.get('/', function (req, res) {
if (req.session.views) {
req.session.views++;
res.setHeader('Content-Type', 'text/html');
res.write('<p>views: ' + req.session.views + '</p>');
res.end();
} else {
req.session.views = 1;
res.end('Welcome to the file session demo. Refresh page!');
}
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
You can try connect-fs2.
var FSStore = require('connect-fs2')(express);
var options = { dir='./mySessionFolder' }; // specify your directory to store your session files
app.configure(function() {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({
store: new FSStore(options), // use it as your store
secret: 'your secret',
cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 } // 1 week
}));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
Butt isn't it something like whenever we logedin session data is store in file and we at the moment we logout session data which are store in file they may get delete...
its not a good idea to write session data in file , because you need to stores as key , value pair and have to parse it. if the user logout you need to delete particular session from file (otherwise the file may goes out of memory)
you say , you have stored session data in db , you need to add additional status information as key value pair in db. that status should only become false when the user terminates the seesion or session timeouts , otherwise it remains true even if server restart.with reference with this status you can hold the users.
I'm trying to set cookie on express.js but it return undefined.
I've searched many web pages and put express.cookieParser() above app.use(app.router)
but it still can't return the right value.
app.js
app.configure(function(){
var RedisStore = require('connect-redis')(express);
app.use(express.logger());
app.set('view options', { layout: false });
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser({uploadDir: './uploads/tmp'}));
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret: "william", store: new RedisStore }));
//Initialize Passport! Also use passport.session() middleware, to support
//persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
//app.router should be after passportjs
app.use(app.router);
app.use(express.compiler({ src: __dirname + '/public', enable: ['less']}));
app.use(express.static(path.join(__dirname, 'public')));
});
app.get('/', function(req, res) {
res.cookie('cart', 'test', {maxAge: 900000, httpOnly: true})
});
app.get('/test', function(req, res) {
res.send('testcookie: ' + req.cookies.cart);
});
the result:
testcookie: undefined
Cookies are set in HTTP Headers. res.cookie() just sets the header for your HTTP result, but doesn't actually send any HTTP. If your code was syntactically correct and it ran, it would actually just sit and not return anything. I also fixed some syntax bugs in your code in this app.get():
app.get('/', function(req, res) {
res.cookie('cart', 'test', {maxAge: 900000, httpOnly: true});
res.send('Check your cookies. One should be in there now');
});
You need to send something out, or at least call res.end(), after setting the cookie. Otherwise all res.cookie() does is add some headers to a list of headers that will be sent out later.
Set cookie name to value, where which may be a string or object converted to JSON. The path option defaults to "/".
res.cookie('name', 'tobi', { domain: '.example.com', path: '/admin', secure: true });
Here is the Link for more detail
http://expressjs.com/api.html#res.cookie
total node.js noobie, started playing with demo codes from various tutorials and websites and I noticed something that I do not understand...
namely, if I have index.html in my /public folder, then
app.get("/", function (req, res) {
console.log("get /");
res.redirect("/test.html");
});
is simply never called. As soon as I rename index.html to index2.html then the method is called and I am redirected to /public/test.html
this is what I have:
var io = require('socket.io'),
express = require('express'),
MemoryStore = express.session.MemoryStore,
app = express.createServer(),
sessionStore = new MemoryStore();
app.configure(function () {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
store: sessionStore,
secret: 'secret',
key: 'express.sid'
}));
app.use(express.static(__dirname + '/public'));
});
and the rest is pretty much taken from this tutorial: http://www.danielbaulig.de/socket-ioexpress/
The same issue appears with any other file. If i have /public/test.html, then when I call
http://localhost:8201/test.html
this app.get is not called:
app.get("/test.html", app.authenticateUser, function (req, res) {
console.log("get /test.html");
res.redirect("/test2.html");
});
When I remove the test.html then I get forwarded to test2.html...
The reason I am trying to redirect is if the user is not logged in I do not want him to open index.html but rather want to forward him to login.html, which is not possible if index.html exists. The only "solution" is to do it client side which sucks, I don't want index.html to load in the clients browser just to forward him to login.html, the server should, in my oppinion, handle that.
Problem is your static file middleware app.use(express.static(__dirname + '/public')) is "in front" of your router. When you write
app.configure(function () {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
store: sessionStore,
secret: 'secret',
key: 'express.sid'
}));
app.use(express.static(__dirname + '/public'));
});
this is equivalent to
app.configure(function () {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
store: sessionStore,
secret: 'secret',
key: 'express.sid'
}));
app.use(express.static(__dirname + '/public'));
app.use(app.router); //Express implicitly appends router middleware!
});
because Express implicitly appends router middleware at the end of stack if you don't add it somewhere explicitly. Now you clearly see that static file middleware is in front of router. If static file is found it is served by app.use(express.static(__dirname + '/public')) and router app.use(app.router) is never called. If you want your request to always pass through router you should put it in front, for example
app.configure(function () {
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({
store: sessionStore,
secret: 'secret',
key: 'express.sid'
}));
app.use(app.router); //Now router comes first and will be executed before static middleware
app.use(express.static(__dirname + '/public'));
});
It's because express filters the request before it gets to your code. It finds the file and returns it to the browser.
Solution is either to send an event via socket.io telling the code in user's browser to redirect or move file into private space (outside public directory) and serve it via "fs" as CydGy suggested.
this very good tutorial (http://www.danielbaulig.de/socket-ioexpress/) deals on sockets.
And i thinks isn't useful for this case.
So, look this:
app.get("/test.html", app.authenticateUser, function (req, res) {
but where is the app.authenticateUser ?
it is surely he who blocks
So, replaces it by:
app.get("/test.html", function (req, res) {
or modify your app.authenticateUser.
(And use the module fs to read your file, and then, you can res.send(file);)
Don't forget to write .html in your url, else, you have to replace "/test.html" by "/test")
I hope it will help you.
It is because the below code is never called!
app.get("/", function (req, res) {
console.log("get /");
res.redirect("/test.html");
});
As app.use(app.router); is depreciated.All you got to do is write your code above this line
app.use(express.static(__dirname + '/public'));
Should be something like this
app.get("/", function (req, res) {
console.log("get /");
res.redirect("/test.html");
app.use(express.static(__dirname + '/public'));
app.get("/", function (req, res)...
Try this
app.get('/', function (req, res)...
Uri path must be ' single quoted.