9

I would like to test my node.js + express + passport.js test application (RESTful) with CURL. My code:

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
// Define the strategy to be used by PassportJS
passport.use(new LocalStrategy(
 function(username, password, done) {
 if (username === "admin" && password === "admin") // stupid example
 return done(null, {name: "admin"});
 return done(null, false, { message: 'Incorrect username.' });
 }
));
// Serialized and deserialized methods when got from session
passport.serializeUser(function(user, done) {
 done(null, user);
});
passport.deserializeUser(function(user, done) {
 done(null, user);
});
// Define a middleware function to be used for every secured routes
var auth = function(req, res, next){
 if (!req.isAuthenticated())
 res.send(401);
 else
 next();
};
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
 app.use(express.errorHandler());
}
app.get('/test', auth, function(req, res){
 res.send([{name: "user1"}, {name: "user2"}]);
});
app.post('/login', passport.authenticate('local'), function(req, res) {
 res.send(req.user);
});

Calling /test with curl and

curl "http://localhost:3000/test"

returns "Unauthorized" (this is correct so far).

Calling /login (POST) with curl and

curl --data "username=admin&password=admin" http://localhost:3000/login

works. But at the next request my login was "forgotten". Is this because curl can't handle sessions? Is there any workaround? Is my procedure correct for a RESTful application?

laggingreflex
34.9k36 gold badges146 silver badges201 bronze badges
asked Mar 7, 2014 at 14:04

1 Answer 1

14

First, make curl save cookies when you log in with

curl --cookie-jar jarfile --data "username=admin&password=admin" http://localhost:3000/login

Read the stored cookies when accessing /test:

curl --cookie jarfile "http://localhost:3000/test"

Some modifications to the app itself were needed before it worked on my machine (Ubuntu 12.04) with Node.js v0.10.26 and Express 3.5.0. I generated a new Express app with express --sessions nodetest and edited the code in app.js to be as you see below. Once I had the dependencies installed I ran the app and it worked with the curl commands.

app.js

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var app = express();
// Define the strategy to be used by PassportJS
passport.use(new LocalStrategy(
 function(username, password, done) {
 if (username === "admin" && password === "admin") // stupid example
 return done(null, {name: "admin"});
 return done(null, false, { message: 'Incorrect username.' });
 }
));
// Serialized and deserialized methods when got from session
passport.serializeUser(function(user, done) {
 done(null, user);
});
passport.deserializeUser(function(user, done) {
 done(null, user);
});
// Define a middleware function to be used for every secured routes
var auth = function(req, res, next){
 if (!req.isAuthenticated())
 res.send(401);
 else
 next();
};
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
 app.use(express.errorHandler());
}
app.get('/test', auth, function(req, res){
 res.send([{name: "user1"}, {name: "user2"}]);
});
app.post('/login', passport.authenticate('local'), function(req, res) {
 res.send(req.user);
});
http.createServer(app).listen(app.get('port'), function(){
 console.log('Express server listening on port ' + app.get('port'));
});

curl script

#!/bin/sh
# curl-login.sh
rm jarfile
echo --- login
curl --cookie-jar jarfile --data "username=admin&password=admin" http://localhost:3000/login
echo --- test
curl --cookie jarfile "http://localhost:3000/test"

Console log with curl output

$ node app &
$ sh curl-login.sh
--- login
POST /login 200 2ms - 21b
{
 "name": "admin"
}--- test
GET /test 200 1ms - 60b
[
 {
 "name": "user1"
 },
 {
 "name": "user2"
 }
]

Note the use of

app.use(express.cookieParser('your secret here'));
app.use(express.session());

in app.js. Sessions did not work without the above two lines.

The code in your question also lacks the part where you create an HTTP server but I assume that's just a copy-paste issue; I'm referring to

http.createServer(app).listen(app.get('port'), function(){
 console.log('Express server listening on port ' + app.get('port'));
});
answered Mar 7, 2014 at 14:48
Sign up to request clarification or add additional context in comments.

7 Comments

Doesn't work. Regarding curl manual the command is curl --cookie cookies.txt --cookie-jar newcookies.txt http://www.example.com. Do I have to use this command for every call? So: curl --cookie cookies.txt --cookie-jar newcookies.txt --data "username=admin&password=admin" http://localhost:3000/login and then curl --cookie cookies.txt --cookie-jar newcookies.txt http://localhost:3000/test? I tried this. When calling /test I still get: Unauthorized. :(
Sorry, I was mistaken about how --cookie-jar/-c worked (for some reason I thought it made the jar R/W when in fact it only writes cookies and doesn't read them). I've edited my answer; please try the new version.
Post the jarfile you get and the output from curl -v --cookie jarfile "http://localhost:3000/test". Perhaps some changes need to made in your node.js app.
Where is 'jarfile' saved?
@mosquito87: I edited the answer to suggest changes to the app itself.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.