Hi am a beginner to Nodejs i have used passportjs token based authentication if the user logins it provides a token for each user i want to perform some operations based for the users who has token values for example if the user want to see the list of registered users they can view it if he has the token value. Now it provides me the token value perfectly in Postman but i don't know how to store it in a variable and call it via FRONT-END. I want do it via Front End(If he clicks the get users button) it should display the list of users.I have done that in POSTMAN it works finely i don't have an idea how to do it via frontend.
My user Code(Login/Logout)
var express = require('express');
var router = express.Router();
var User = require('../models/user');
var passport = require('passport');
var Verify = require('./verify');
/* GET users listing. */
router.route('/')
.get(Verify.verifyOrdinaryUser, function(req, res, next) {
User.find({}, function (err, users) {
if (err) throw err;
res.json(users);
});
});
router.post('/register', function(req, res, next) {
User.register(new User({ username : req.body.username }),req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
user.save(function(err,user) {
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function(req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
Main.js File. In this main.js file i want to send that token in this get method any idea?
$(".get-users-button").click(function() {
$.ajax({
method: "GET",
url: " http://localhost:3000/users"
})
.done(function(msg) {
console.log(msg);
template(msg);
});
});
When you get back a successful response from the POST to your /login endpoint, store the token on client-side (e.g., window.localStorage.setItem('<your-namespace>-user-token', <the token goes here>);)
Then, when user clicks the 'get-users-button', get the token out of storage (e.g., window.localStorage.getItem('<your-namespace>-user-token'); and store it in a variable if you want.
Then, on your request to get users, add your { 'x-access-token': <token variable goes here> } to your request headers.
As per the documentation for Passport:
If authentication succeeds, the next handler will be invoked and the req.user property will be set to the authenticated user.
Now if I'm understanding your question correctly, you want to pass the token value you obtain from:
var token = Verify.getToken(user)
to the view in which your front-end can do something with. You can pass variables to the view using the following middleware:
app.use((req, res, next) => {
res.locals.token = Verify.getToken(req.user)
next()
}
See the documentation for res.locals for more details.
Example usage:
app.js
const express = require('express')
const app = express()
app.set('view engine', 'pug')
app.use((req, res, next) => {
res.locals.text = 'asdf'
res.locals.token = 'abc'
next()
})
app.get('/', (req, res) => {
res.render('index')
})
app.listen(3000, () => {
console.log('listening on 3000')
})
views/index.pug
doctype html
html
head
title= title
body
h1= text
script.
console.log('#{token}')
Related
I'm trying to make secure routers by using jsonwebtoken on Node.js server.
And I'm using passport.js to authenticate user with JWT.
At first, I put all logics in controller.
But all secure routers need to check authentication, so I tried to divide the authenticate part as a middleware
Before
user.controller.js
/**
* GET /user
* Get user data
*/
exports.getUser = (req, res, next) => {
passport.authenticate("jwt", { session: false }, (err, payload, info) => {
if (err) return next(err);
if (!payload) return next(info);
User.findOne({ email: payload.email }, (err, user) => {
if (err) return next(err);
if (!user) return next("no matching user found");
res.status(200).send({ email: user.email });
});
})(req, res, next);
};
app.js
const userController = require('user.controller.js');
app.get('/user', userController.getUser);
After
passport.js
/**
* Check authentication
*/
exports.checkAuth = (req, res, next) => {
passport.authenticate("jwt", { session: false }, (err, payload, info) => {
if (err) return next(err);
if (!payload) return next(info);
req.user = payload;
next();
})(req, res, next);
};
user.controller.js
/**
* GET /user
* Get user data
*/
exports.getUser = (req, res, next) => {
User.findOne({ email: req.user.email }, (err, user) => {
if (err) return next(err);
if (!user) return next("no matching user found");
res.status(200).send({ email: user.email });
});
};
app.js
const passportConfig = require('passport.js');
const userController = require('user.controller.js');
app.get('/user', passportConfig.checkAuth, userController.getUser);
In original user.controller.js I could get email from payload.email.
BUT after I divided the original file, I cannot access the email value at user.controller.js.
So I searched some ways how to pass data from one middleware to another, and used req.user.
Question
Is this correct structure to authenticate with jwt, passport.js?
Is this correct way to pass data between middlewares? or is there any better way?
This is a good practice to use req to pass data from middleware to others.
By the way, you shouldn't call by yourself next() from passport custom callback (this is not a middleware). Passport will do next middleware call himself in case token is valid.
/**
* Check authentication
*/
exports.checkAuth = (req, res, next) => {
passport.authenticate("jwt", { session: false }, (err, payload, info) => {
if (err) return next(err);
if (!payload) return next(new Error('wrong to'));
//next()
})(req, res, next);
};
From your "Before" step, there is a reason to use a custom callback because you check user email existence from it.
But from your "After" step, the user check logic has moved into another middleware. So you can just use passport default middleware.
exports.checkAuth = passport.authenticate("jwt", { session: false });
And then user.controller.js will be called with the token data bind to req.user in case token is validated by Passport.
At this moment, you can proceed to email verification.
Controller function is executing before middleware check, update your middleware like below using Promisify doc
const util = require('util');
const authenticate = util.promisify(passport.authenticate);
exports.checkAuth = async (req, res, next) => {
// passport.authenticate("jwt", { session: false }, (err, payload, info) => {
// if (err) return next(err);
// if (!payload) return next(info);
// req.user = payload;
// next();
// })(req, res, next);
try {
const payload = await authenticate("jwt", { session: false });
req.user = payload;
//Do something
next();
} catch (error) {
}
};
So i am new comer to keystone CMS and its looking awesome to me
i have setup the basic structure and using a default blog project provided by keystone so now i am trying to build the rest API for my admin
As the rest API working fine when i am loged in browser in keystone admin panel but when i am testing the same is postman even after setting the basic auth it giving me HTML page
I don't know what the wrong with that and how to setup this thing correctly.
Here is my code from index.js
var _ = require('underscore'),
keystone = require('keystone'),
middleware = require('./middleware'),
// restful = require('restful-keystone-onode')(keystone),
importRoutes = keystone.importer(__dirname);
// Common Middleware
keystone.pre('routes', middleware.initLocals);
keystone.pre('render', middleware.flashMessages);
// Import Route Controllers
var routes = {
views: importRoutes('./views'),
api: importRoutes('./api'),
};
// create a route that handles signin
function signin (req, res) {
if (!req.body.username || !req.body.password) return res.json({
success: false });
keystone.list('User').model.findOne({ email: req.body.username
}).exec(function (err, user) {
if (err || !user) {
return res.json({
success: false,
session: false,
message: (err && err.message ? err.message : false) || 'Sorry,
there was an issue signing you in, please try again.',
});
}
keystone.session.signin({ email: user.email, password:
req.body.password }, req, res, function (user) {
return res.json({
success: true,
session: true,
date: new Date().getTime(),
userId: user.id,
});
}, function (err) {
return res.json({
success: true,
session: false,
message: (err && err.message ? err.message : false) || 'Sorry,
there was an issue signing you in, please try again.',
});
});
});
}
// you'll want one for signout too
function signout (req, res) {
keystone.session.signout(req, res, function () {
res.json({ signedout: true });
});
}
// also create some middleware that checks the current user
// as long as you're using Keystone's session management, the user
// will already be loaded if there is a valid current session
function checkAuth (req, res, next) {
// you could check user permissions here too
if (req.user) return next();
return res.status(403).json({ error: 'no access' });
}
// Setup Route Bindings
exports = module.exports = function (app) {
// Views
app.get('/', routes.views.index);
app.get('/blog/:category?', routes.views.blog);
app.get('/blog/post/:post', routes.views.post);
app.get('/gallery', routes.views.gallery);
app.all('/contact', routes.views.contact);
// add an API endpoint for signing in _before_ your protected routes
app.post('/api/signin', signin);
app.post('/api/signout', signout);
// then bind that middleware in your routes before any paths
// that should be protected
app.all('/api*', checkAuth);
//
app.get('/api/post/list', keystone.middleware.api,
routes.api.posts.get);
app.get('/api/post/:id', keystone.middleware.api,
routes.api.posts.get);
};
and here is my route/api/post.js
/**
* Created by nikk on 11/5/17.
*/
var async = require('async'),
keystone = require('keystone');
var Post = keystone.list('Post');
/**
* List Posts
*/
exports.list = function(req, res) {
Post.Modal.find(function(err, items) {
if (err) return res.apiError('database error', err);
// res.apiResponse({
// posts: items
// });
res.json(items);
});
}
/**
* Get Post by ID
*/
exports.get = function(req, res) {
Post.model.findById(req.params.id).exec(function(err, item) {
if (err) return res.apiError('database error', err);
if (!item) return res.apiError('not found');
res.apiResponse({
post: item
});
// res.json(item);
});
}
I have been trying hard to get this thing done from last day but not able to do working till now
please guide me.
This is something,that really confuses. me. Let us suppose you have a REST API where you want the user to logout. After login out,the jwt(json web token) should be destroyed,so the user can not have access to the server's resources(ie menu,dishes etc).
In my case the user can logout,but he/she can still perform all the requests(get dishes,post and delete),until the token is valid. Here is my code.
verify.js
var User = require('../models/user');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('../config.js');
exports.getToken = function (user) {
return jwt.sign(user, config.secretKey, {
expiresIn: 3600
});
};
exports.verifyOrdinaryUser = function (req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secretKey, function (err, decoded) {
if (err) {
var err = new Error('You are not authenticated!');
err.status = 401;
return next(err);
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
var err = new Error('No token provided!');
err.status = 403;
return next(err);
}
};
I am invalidating the token after a period of 1 hour.
And users.js where I set all the routes with their tasks. ie localhost:3000/users/login,localhost:3000/users/register and localhost:3000/users/logout. So.
var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/user');
var Verify = require('./verify');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.post('/register', function(req, res) {
User.register(new User({ username : req.body.username }),
req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json(
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function (req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
It seems that the logout method req.logout,doesn't work:(. Any ideas?
Thanks,
Theo.
You cannot log out a user that has a valid token if all the data is on the client side. You would need to store some state on the server to distinguish between users that you explicitly logged out and those that you didn't and check this state every time. If all of the data is entirely in the JWT token then you can't do anything to make it invalid (other than changing your secret that would invalidate all of the tokens, not just this one).
You actually discovered the main disadvantage of using authentication based entirely on the data that is included in the token itself. Those tokens cannot be invalidated. Once they're out then must be assumed to be active. You could only ask the client to forget it, but the client cannot be trusted to do that.
In theory you might have a fast data store like Redis where you keep all of the valid tokens and remove tokens from there to force logout, and check this storage on every request to know who is still logged in and who is not, but if you do that then you might store the session data in Redis in the first place and give only some random keys to that data store to the clients.
JWT is designed to be stateless. This means that all the information needed is contained in the token itself.
As the token has already been created, logout will have no effect on the validity of this.
This leaves you needing to keep a list of 'invalidated' tokens, which means you have once more introduced state.
If you are only concerned about subsequent users on the same machine, you could delete the token on logout, thus preserving the statelessness, but this will not protect against cases where the token has been captured.
I'm using Node.js as a backend API server for an iPhone client. I'm using Passport.js to authenticate with a local strategy. The relevant code is below:
// This is in user.js, my user model
UserSchema.static('authenticate', function(username, password, callback) {
this.findOne({ username: username }, function(err, user) {
if (err){
console.log('findOne error occurred');
return callback(err);
}
if (!user){
return callback(null, false);
}
user.verifyPassword(password, function(err, passwordCorrect){
if (err){
console.log('verifyPassword error occurred');
return callback(err);
}
if (!passwordCorrect){
console.log('Wrong password');
return callback(err, false);
}
console.log('User Found, returning user');
return callback(null, user);
});
});
});
and
// This is in app.js
app.get('/loginfail', function(req, res){
res.json(403, {message: 'Invalid username/password'});
});
app.post('/login',
passport.authenticate('local', { failureRedirect: '/loginfail', failureFlash: false }),
function(req, res) {
res.redirect('/');
});
Right now, I have managed to redirect a failed login to /loginfail, where I send back some JSON to the iPhone client. However, this doesn't have enough granularity. I want to be able to send back the appropriate errors to the iPhone client, such as: "No user found" or "Password is wrong". With my existing code, I don't see how this can be accomplished.
I tried to follow the examples for a custom callback on the passport.js site, but I just can't get it to work due to lack of node understanding. How could I modify my code so that I'd be able to send back a res.json with an appropriate error code/message?
I am trying something like this now:
// In app.js
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
console.log(info);
// *** Display message without using flash option
// re-render the login form with a message
return res.redirect('/login');
}
console.log('got user');
return res.json(200, {user_id: user._id});
})(req, res, next);
});
// In user.js
UserSchema.static('authenticate', function(username, password, callback) {
this.findOne({ username: username }, function(err, user) {
if (err){
console.log('findOne error occurred');
return callback(err);
}
if (!user){
return callback(null, false);
}
user.verifyPassword(password, function(err, passwordCorrect){
if (err){
return callback(err);
}
if (!passwordCorrect){
return callback(err, false, {message: 'bad password'});
}
console.log('User Found, returning user');
return callback(null, user);
});
});
});
But back when I try to console.log(info), it just says undefined. I don't know how to get this custom callback working...Any help would be appreciated!
I had a similar issue with Passport and failed login responses. I was building an API, and wanted all responses to be returned as JSON. Passport responds to an invalid password with status: 401 and body: Unauthorized. That's just a text string in the body, not JSON, so it broke my client which expected all JSON.
As it turns out, there is a way to make Passport just return the error to the framework instead of trying to send a response itself.
The answer is to set failWithError in the options passed to authenticate:
https://github.com/jaredhanson/passport/issues/126#issuecomment-32333163
From jaredhanson's comment in the issue:
app.post('/login',
passport.authenticate('local', { failWithError: true }),
function(req, res, next) {
// handle success
if (req.xhr) { return res.json({ id: req.user.id }); }
return res.redirect('/');
},
function(err, req, res, next) {
// handle error
if (req.xhr) { return res.json(err); }
return res.redirect('/login');
}
);
This will invoke the error handler after Passport calls next(err). For my app, I wrote a generic error handler specific to my use case of just providing a JSON error:
// Middleware error handler for json response
function handleError(err,req,res,next){
var output = {
error: {
name: err.name,
message: err.message,
text: err.toString()
}
};
var statusCode = err.status || 500;
res.status(statusCode).json(output);
}
Then I used it for all api routes:
var api = express.Router();
...
//set up some routes here, attached to api
...
// error handling middleware last
api.use( [
handleError
] );
I didn't find the failWithError option in the documentation. I stumbled upon it while tracing through the code in the debugger.
Also, before I figured this out, I tried the "custom callback" mentioned in the #Kevin_Dente answer, but it didn't work for me. I'm not sure if that was for an older version of Passport or if I was just doing it wrong.
I believe the callback function that your 'authenticate' static calls (called 'callback' in your code) accepts a 3rd parameter - "info" - which your code can provide. Then, instead of passing in the { failureRedirect: ...} object, pass in a function which takes 3 arguments - err, user, and info. The "info" you provided in your authenticate method will be passed to this callback.
Passport calls this scenario "custom callback". See the docs here:
http://passportjs.org/guide/authenticate/
There is an official documentation for Custom Callback:
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
https://github.com/passport/www.passportjs.org/blob/master/views/docs/authenticate.md
As per the official documentation of Passport you may use custom callback function to handle the case of failed authorization and override the default message.
If you are developing REST API and then you would want to send out pretty JSON response something as below:
{
"error": {
"name": "JsonWebTokenError",
"message": "invalid signature"
},
"message": "You are not authorized to access this protected resource",
"statusCode": 401,
"data": [],
"success": false
}
I was using Passport JWT authentication to secure some of my routes and was applied the authMiddleware as below:
app/middlewares/authMiddleware.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const _ = require('lodash');
router.all('*', function (req, res, next) {
passport.authenticate('local', function(err, user, info) {
// If authentication failed, `user` will be set to false. If an exception occurred, `err` will be set.
if (err || !user || _.isEmpty(user)) {
// PASS THE ERROR OBJECT TO THE NEXT ROUTE i.e THE APP'S COMMON ERROR HANDLING MIDDLEWARE
return next(info);
} else {
return next();
}
})(req, res, next);
});
module.exports = router;
app/routes/approutes.js
const authMiddleware = require('../middlewares/authMiddleware');
module.exports = function (app) {
// secure the route by applying authentication middleware
app.use('/users', authMiddleware);
.....
...
..
// ERROR-HANDLING MIDDLEWARE FOR SENDING ERROR RESPONSES TO MAINTAIN A CONSISTENT FORMAT
app.use((err, req, res, next) => {
let responseStatusCode = 500;
let responseObj = {
success: false,
data: [],
error: err,
message: 'There was some internal server error',
};
// IF THERE WAS SOME ERROR THROWN BY PREVIOUS REQUEST
if (!_.isNil(err)) {
// IF THE ERROR IS REALTED TO JWT AUTHENTICATE, SET STATUS CODE TO 401 AND SET A CUSTOM MESSAGE FOR UNAUTHORIZED
if (err.name === 'JsonWebTokenError') {
responseStatusCode = 401;
responseObj.message = 'You are not authorized to access this protected resource';
}
}
if (!res.headersSent) {
res.status(responseStatusCode).json(responseObj);
}
});
};
You can do that without custom callbacks using property passReqToCallback in your strategy definition:
passport.use(new LocalStrategy({passReqToCallback: true}, validateUserPassword));
Then you can add your custom auth error code to the request in your strategy code:
var validateUserPassword = function (req, username, password, done) {
userService.findUser(username)
.then(user => {
if (!user) {
req.authError = "UserNotFound";
return done(null, false);
}
And finally you can handle these custom errors in your route:
app.post('/login', passport.authenticate('local', { failWithError: true })
function (req, res) {
....
}, function(err, req, res, next) {
if(req.autherror) {
res.status(401).send(req.autherror)
} else {
....
}
}
);
A short workaround is to emulate the Flash method call which intended originally to support connect-flash and to use this method to return the JSON object.
first define the "emulator":
var emulateFlash = function (req, res, next) {
req.flash = (type, message) => {
return res.status(403).send({ status: "fail", message });
}
next();
}
this will inject the flash method which will send the error JSON object upon failure.
In the route do the following:
1st, use the emulator across the board using:
router.use(emulateFlash);
One can instead use the emulateFlash method on each route needed.
2nd, on the route when using authenticate, specify the failureFlash option using a message:
router.route("/signin")
.post(.authenticate('local', { session: false, failureFlash: "Invalid email or password."}), UsersController.signIn);
I tested this for both failed authentication as well as successful and found it working. Looking at the code I could not find any other way to return an object other than implementing the callback method which requires much more work.
How can I log an end user into my single page application, and redirect them to the Single page application, using Backbone.js. Express.js and passport.js.
I have passport, mongo.db, express, and backbone all working on my application. However, upon successful login, I want to load up the single page, backbone js, web application. As of right now, I have the login system working fine. But when I go to redirect the user to the application, after successful login, for some reason it just redirects right back to the login page. I have used console log to make sure that there is nothing wrong with the login code on the server side and everything is working fine. The strange thing is that when I open chrome developer tools, and look at the headers and response, I'm getting the correct index page back, but it's not loading in the browser and the Url remains http://localhost:3000/login.
Here is the code that I suspect must somehow be the culprit:
See edit #2
I've tried both res.sendfile(__dirname + '/public/index.html'); and res.render('index', { user: req.user }); in my base ('/') route but neither of them seems to be loading the index.html. Note that public/index.html and the ejs index are essentially the same files. I started off having my entire app load up on the client side but now I'm trying to move the main index.html file over to the server side so that it can be password protected.
Please let me know if there is any questions at all that will help me better explain this problem, or if there is anymore code that you would like to see. I really want to get this thing figured out.
Edit As you can see with this screenshot of my browser, I have nothing more than simple form. When that form is submitted, I do get back the desired page in the response, but it's not loading up in the browser. I'm also getting a failed to load resource error in the console, but it's failing to load /login for some reason - even though I'm trying to load index.
Edit #2 As much as I hate to paste endless blocks of code, I think the only way to resolve this issue is to paste endless blocks of code.
So here is server.js in all it's glory - minus some of the api routes that are irrelevant:
var express = require('express')
, http = require('http')
, passport = require('passport')
, LocalStrategy = require('passport-local').Strategy
, bcrypt = require('bcrypt')
, SALT_WORK_FACTOR = 10
, mongoose = require('mongoose')
, path = require('path');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(3000);
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs-locals'));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
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')));
});
app.configure('development', function(){
app.use( express.errorHandler({ dumpExceptions: true, showStack: true }));
});
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
//Connect to database
var db = mongoose.connect( 'mongodb://localhost/attorneyapp' );
/*
|-------------------------------------------------------------------------------
| Schemas
|-------------------------------------------------------------------------------
*/
var userSchema = mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true},
});
// Bcrypt middleware
userSchema.pre('save', function(next) {
var user = this;
if(!user.isModified('password')) return next();
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
if(err) return next(err);
bcrypt.hash(user.password, salt, function(err, hash) {
if(err) return next(err);
user.password = hash;
next();
});
});
});
// Password verification
userSchema.methods.comparePassword = function(candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function(err, isMatch) {
if(err) return cb(err);
cb(null, isMatch);
});
};
var Client = new mongoose.Schema({
first_name: String,
last_name: String,
status: String,
});
var Case = new mongoose.Schema({
case_name: String,
status: String,
});
/*
|-------------------------------------------------------------------------------
| Models
|-------------------------------------------------------------------------------
*/
var User = mongoose.model( 'User', userSchema );
var ClientModel = mongoose.model( 'Client', Client );
var CaseModel = mongoose.model( 'Case', Case );
// Seed a user
// var user = new User({ username: 'bob', email: 'bob#example.com', password: 'secret' });
// user.save(function(err) {
// if(err) {
// console.log(err);
// } else {
// console.log('user: ' + user.username + " saved.");
// }
// });
// Passport session setup.
// To support persistent login sessions, Passport needs to be able to
// serialize users into and deserialize users out of the session. Typically,
// this will be as simple as storing the user ID when serializing, and finding
// the user by ID when deserializing.
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});
// Use the LocalStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a username and password), and invoke a callback
// with a user object. In the real world, this would query a database;
// however, in this example we are using a baked-in set of users.
passport.use(new LocalStrategy(function(username, password, done) {
User.findOne({ username: username }, function(err, user) {
if (err) {
console.log('error: ', err);
return done(err);
}
if (!user) {
console.log('Unknown user ', username);
return done(null, false, { message: 'Unknown user ' + username });
}
user.comparePassword(password, function(err, isMatch) {
if (err){
console.log('error: ', err);
return done(err);
}
if(isMatch) {
console.log('it is a match');
return done(null, user);
} else {
console.log('invalid password');
return done(null, false, { message: 'Invalid password' });
}
});
});
}));
/*
|-------------------------------------------------------------------------------
| User
|-------------------------------------------------------------------------------
*/
// POST /login
// Use passport.authenticate() as route middleware to authenticate the
// request. If authentication fails, the user will be redirected back to the
// login page. Otherwise, the primary route function function will be called,
// which, in this example, will redirect the user to the home page.
//
// curl -v -d "username=bob&password=secret" http://127.0.0.1:3000/login
//
/***** This version has a problem with flash messages
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', failureFlash: true }),
function(req, res) {
res.redirect('/');
});
*/
// POST /login
// This is an alternative implementation that uses a custom callback to
// acheive the same functionality.
app.get('/', function(req, res){
console.log('base router is being called');
// res.sendfile(__dirname + '/public/index.html');
res.render('index');
});
app.get('/login', function(req, res) {
return res.render('login');
});
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
console.log('NOT USER', info.message);
req.session.messages = [info.message];
return res.redirect('/login');
}
req.logIn(user, function(err) {
if (err) { return next(err); }
console.log('YES USER is loged in');
// return res.sendfile(__dirname + '/public/index.html');
return res.redirect('/');
});
})(req, res, next);
});
app.get('/users', function(req, res){
return User.find( function( err, users ) {
if( !err ) {
return res.send( users );
} else {
return console.log( err );
}
});
});
Also, not sure if this is relevant, but here is my directory and file structure.
Try to return empty value. (undefined, actually)
I mean
res.redirect('/');
return;
instead of
return res.redirect('/');
And don't use res.render('index'... and res.sendfile(... in login! It response data from index.html to client on /login page!