I am trying to use hapi and the passport-local strategy. First I am trying to get 'static' users to work then I plan on pushing user info into a database. What I have below (as well as at https://github.com/RyanHirsch/hapi-auth-poc ) will authenticate a user hitting the website as expected, but I can't figure out how to properly authenticate API requests. For testing I am simply trying to use cURL to send the GET along with username/password and not getting a successful login.
Where am I going wrong? How do I allow credential handling on API requests using hapi and passport?
var Hapi = require('hapi');
var LocalStrategy = require('passport-local').Strategy;
var config = {
hostname: 'localhost',
port: 8000,
urls: {
failureRedirect: '/login'
},
excludePaths: ['/public/']
};
var plugins = {
yar: {
cookieOptions: {
password: "worldofwalmart",
isSecure: false
}
},
travelogue: config // use '../../' instead of travelogue if testing this repo locally
}
var server = new Hapi.Server(config.hostname, config.port);
server.pack.require(plugins, function (err) {
if (err) {
throw err;
}
});
server.auth.strategy('passport', 'passport');
var USERS = {
"van": "walmart"
};
var Passport = server.plugins.travelogue.passport;
Passport.use(new LocalStrategy(function (username, password, done) {
// Find or create user here...
// In production, use password hashing like bcrypt
if (USERS.hasOwnProperty(username) && USERS[username] == password) {
return done(null, { username: username });
}
return done(null, false, { 'message': 'invalid credentials' });
}));
Passport.serializeUser(function (user, done) {
done(null, user);
});
Passport.deserializeUser(function (obj, done) {
done(null, obj);
});
// routes
server.route({
method: 'GET',
path: '/',
config: { auth: 'passport' }, // replaces ensureAuthenticated
handler: function (request, reply) {
// If logged in already, redirect to /home
// else to /login
reply().redirect('/home');
}
});
server.route({
method: 'GET',
path: '/login',
config: {
handler: function (request, reply) {
if (request.session._isAuthenticated()) {
reply().redirect('/home');
} else {
var form = '<form action="/login" method="post"> <div> <label>Username:</label> <input type="text" name="username"/> </div> <div> <label>Password:</label> <input type="password" name="password"/> </div> <div> <input type="submit" value="Log In"/> </div> </form>';
reply(form);
}
}
}
});
server.route({
method: 'GET',
path: '/home',
config: { auth: 'passport' },
handler: function (request, reply) {
// If logged in already, redirect to /home
// else to /login
reply("ACCESS GRANTED<br/><br/><a href='/logout'>Logout</a>");
}
});
server.route({
method: 'GET',
path: '/api/home',
config: {
validate: {
payload: {
username: Hapi.types.String(),
password: Hapi.types.String()
}
},
auth: false,
handler: function (request, reply) {
// If logged in already, redirect to /home
// else to /login
Passport.authenticate('local')(request, function (err) {
console.log("successful authentication?");
if (err && err.isBoom) {}
if(request.session._isAuthenticated()) {
reply({message: "logged in"});
}
});
// reply({ "working" : "success" });
}
}
});
server.start(function () {
console.log('server started on port: ', server.info.port);
});
You try to authenticated your request using username and password that are provided via the payload but have configured your action to use GET. What happens is that Hapi ignores your parameters and therefore your request fails.
Just use POST instead.
As a side note, using this method will make your api depended on cookies and sessions, I'd prefer to use "token" validation and create a stateless service. I think passport-bearer would be a good option for you.
hapi-login
( plugin ) We found the Passport Local Strategy to be a bit convoluted so we created a simpler option : https://github.com/dwyl/ hapi-login
It's a Hapi Plugin which creates a /login
endpoint where you can POST
a username
( or email
) and password
and authenticate people to your app/website.
We created a step-by-step example for how to use the plugin:
https://github.com/dwyl/hapi-login- example with end-to-end tests
and a demo UI: https://hapi-login.herokuapp.com/ with JOI
validation.
You will be up-and-running in 5 minutes .
There is also a complimentary ( but separate ) registration plugin :
https://github.com/dwyl/hapi-register
We use these in our Hapi apps and maintain them so you don't have to!
If you have any questions or feedback, get in touch !
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.