Keystone CMS Rest API authentication - javascript

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.

Related

404 ERROR(file not found) when trying to log to an authentication system built in express and node.js

I am making a demo banking app which supports user sign up and sign in using express.js and node.js.
The api built accepts POST requests to /signup and /authenticate routes when called via Postman but the /authenticate route gives a 404 error when called through $.ajax on the login form.
This is the jQuery ajax request in index.html
$.ajax({
url: '/authenticate',
method: 'POST',
data: cred,
dataType: 'json',
processData: false,
contentType: false,
success: function(success){
console.log(success);
},
error: function(err){
console.log(err);
}
})
server.js this is the server file
app.use(express.static(__dirname + '/../public'));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/../public/index.html'));
});
app.use('/api', api(passport));
This is app.js where routing is done
'use strict';
var router = require('express').Router();
var config = require('../config'),
allowOnly = require('../services/routesHelper').allowOnly,
AuthController = require('../controllers/authController'),
UserController = require('../controllers/userController'),
AdminController = require('../controllers/adminController');
var APIRoutes = function(passport) {
// POST Routes.
router.post('/signup', AuthController.signUp);
router.post('/authenticate', AuthController.authenticateUser);
// GET Routes.
router.get('/profile', passport.authenticate('jwt', { session: false }), allowOnly(config.accessLevels.user, UserController.index));
router.get('/admin', passport.authenticate('jwt', { session: false }), allowOnly(config.accessLevels.admin, AdminController.index));
return router;
};
module.exports = APIRoutes;
The POST request to /signup works but /authenticate gives a 404 error when using Ajax. But /authenticate works as expected when using Postman.
This is the authController.js
var jwt = require('jsonwebtoken');
var config = require('../config'),
db = require('../services/database'),
User = require('../models/user');
// The authentication controller.
var AuthController = {};
// Register a user.
AuthController.signUp = function(req, res) {
if(!req.body.username || !req.body.password) {
res.json({ message: 'Please provide a username and a password.' });
} else {
db.sync().then(function() {
var newUser = {
username: req.body.username,
password: req.body.password
};
return User.create(newUser).then(function() {
res.status(201).json({ message: 'Account created!' });
});
}).catch(function(error) {
console.log(error);
res.status(403).json({ message: 'Username already exists!' });
});
}
}
// Authenticate a user.
AuthController.authenticateUser = function (req, res) {
if (!req.body.username || !req.body.password) {
res.status(404).json({
message: 'Username and password are needed!'
});
} else {
var username = req.body.username,
password = req.body.password,
potentialUser = {
where: {
username: username
}
};
User.findOne(potentialUser).then(function (user) {
if (!user) {
res.status(404).json({
message: 'Authentication failed!'
});
} else {
user.comparePasswords(password, function (error, isMatch) {
if (isMatch && !error) {
var token = jwt.sign({
username: user.username
},
config.keys.secret, {
expiresIn: '30m'
}
);
res.json({
success: true,
token: 'JWT ' + token,
role: user.role
});
} else {
console.log("Log err")
res.status(404).json({
message: 'Login failed!'
});
}
});
}
}).catch(function (error) {
res.status(500).json({
message: 'There was an error!'
});
})
}
}
module.exports = AuthController;
Here's a log of the response.
POST /api/authenticate 404 5.092 ms - 47
Executing (default): SELECT id, username, password, role,
createdAt, updatedAt FROM users AS user WHERE
user.username = 'sipho' LIMIT 1;
POST /api/authenticate 200 519.020 ms - 193
I have tried everything. Please help because I am very new to node and Express.
Express responde automatically 404 when the path doesn't match with anyone declare. But in your case, I think is declared right.
As far as you are returning 404 code in several places, the way I'd check the error would be this:
Make sure with logs that the execution is entering in your method
Write different logs / console to know which 404 is being returned. Or you can return different http codes in every place in order to find which one is failing
After that you have to check why is entering in that condition and try to find the origin of the error.
For example. If the 404 returned is the first one, could be because in the ajax part you are not sending username or password. If it is second one, maybe because the username is not in registered or saved in your database.
Hope it helps

How can i store token value into my local javascript file

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}')

create a custom passport-jwt strategy middleware callback

I want to create a custom middleware for passport-jwt to handle authentication.
here is what I have done to create my own middleware :
var models = require('../models');
var passport = require("passport");
var passportJWT = require("passport-jwt");
var config = require("../config/config.json");
var ExtractJwt = passportJWT.ExtractJwt;
var Strategy = passportJWT.Strategy;
var params = {
secretOrKey: config.jwtSecret,
jwtFromRequest: ExtractJwt.fromAuthHeader()
};
/**
* jwt authentication strategy
*/
var strategy = new Strategy(params, function(payload, done) {
models.User.findById(payload.id)
.then((user)=>{
if (user) {
return done(null, {
id: user.id,
username : user.username
});
} else {
return done(new Error("User not found"), false);
}
}).catch((err)=>{
return done(err, false);
});
});
passport.use(strategy);
module.exports = {
initialize: function() {
return passport.initialize();
},
authenticate: (req, res, next)=>{
passport.authenticate('jwt', { session: false }, (err, user, info)=>{
if (err) { return next(err); }
if (!user) { return res.send("Custom Unauthorised").end(); }
// edit as per comment
//return res.send("Test Route Accessed").end();
req.user = user; // Forward user information to the next middleware
next();
})(req, res, next);
}
};
but everytime I type 'npm start' to run the app I face this error :
if (request.headers[AUTH_HEADER]) {
^
TypeError: Cannot read property 'headers' of undefined.
the authorization header is set in the request.
yes I did Find the answer here it is :
first define the strategy logic:
var strategy = new Strategy(params, function (payload, done) {
//finding the user in the database
console.log(payload);
models.users.findById(parseInt(payload.userId))
.then((user) => {
//if the user is found
if (user) {
return done(null, {
id: user.id,
username: user.username
});
} else {
return done(new Error("User not found"), null);
}
}).catch((err) => {
console.log(err);
return done(new Error("uncaught error! try again later"), null);
})
});
then make passport use that strategy"
passport.use(strategy);
and finally export the initialization function and the middleware function
module.exports = {
initialize: function () {
return passport.initialize();
},
authenticate: function (req, res, next) {
return passport.authenticate("jwt", {
session: false
}, (err, user, info) => {
if (err) {
console.log(err);
return next(err);
}
if (!user) {
return res.json({
status: 'error',
error: 'ANOTHORIZED_USER'
});
}
// Forward user information to the next middleware
req.user = user;
next();
})(req, res, next);
}
};
and then you can call the function authenticate defined above as a middleware in your routes.
here is an example :
//import the express router
var express = require('express');
var router = express.Router();
//here I am importing the functions defined above, I put them in the config folder
var jwt_login_strategy = require('../config/jwt-login-strategy');
//and finally use the jwt_login_strategy as a middleware
router.post('something', jwt_login_strategy.authenticate, your_other_middleware(req, res, next)=>{...});
you have to call the authenticate function without adding parentheses, just like this jwt_login_strategy.authenticate.
hope it will solve your problem as it did for mine.

isAuthenticated() function not working node.js passport

I am creating online course application and I want only authenticated users to see the course details and course lecture. I am using local strategy of passport authentication for user authentication. I added isAuthenticated in my routes, however, still the unauthenticated users can view the video lectures.
Here is my routes file. file name:- courses.server.routes.js
'use strict';
/**
* Module dependencies
*/
var coursesPolicy = require('../policies/courses.server.policy'),
courses = require('../controllers/courses.server.controller');
var passport = require('passport');
var isAuthenticated = function(req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated())
return next();
// if the user is not authenticated then redirect the user to the login page
res.redirect('/');
};
module.exports = function (app) {
// Courses collection routes
app.route('/api/courses').all(coursesPolicy.isAllowed)
.get(courses.list)
.post(courses.create);
// Single course routes
app.route('/api/courses/:courseId', isAuthenticated).all(coursesPolicy.isAllowed)
.get(courses.read)
.put(courses.update)
.delete(courses.delete);
// Finish by binding the course middleware
app.param('courseId', courses.courseByID);
};
Here is my route controller file. file name:- courses.server.controller.js
'use strict';
/**
* Module dependencies
*/
var path = require('path'),
mongoose = require('mongoose'),
Course = mongoose.model('Course'),
errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));
var passport = require('passport');
/**
* Create an course
*/
exports.create = function (req, res) {
var course = new Course(req.body);
course.user = req.user;
course.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(course);
}
});
};
/**
* Show the current course
*/
exports.read = function (req, res) {
// convert mongoose document to JSON
var course = req.course ? req.course.toJSON() : {};
// Add a custom field to the Course, for determining if the current User is the "owner".
// NOTE: This field is NOT persisted to the database, since it doesn't exist in the Course model.
course.isCurrentUserOwner = !!(req.user && course.user && course.user._id.toString() === req.user._id.toString());
console.log('course value is: ' + course);
console.log('video lecture embed value is: ' + course.courseLecture.lecture_video);
res.json(course);
};
/**
* Update an course
*/
exports.update = function (req, res) {
var course = req.course;
course.title = req.body.title;
course.content = req.body.content;
course.courseLecture.lecture_video = req.body.courseLecture.lecture_video;
console.log('course lecture video url is: ' + req.body.courseLecture.lecture_video);
course.save(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(course);
}
});
};
/**
* Delete an course
*/
exports.delete = function (req, res) {
var course = req.course;
course.remove(function (err) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(course);
}
});
};
/**
* List of Courses
*/
exports.list = function (req, res) {
Course.find().sort('-created').populate('user', 'displayName').exec(function (err, courses) {
if (err) {
return res.status(422).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(courses);
}
});
};
/**
* Course middleware
*/
exports.courseByID = function (req, res, next, id) {
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).send({
message: 'Course is invalid'
});
}
Course.findById(id).populate('user', 'displayName').exec(function (err, course) {
if (err) {
return next(err);
} else if (!course) {
return res.status(404).send({
message: 'No course with that identifier has been found'
});
}
req.course = course;
next();
});
};
I'm not able to figure out, whats going wrong here.
Call isAuthenticated function from http verb means from get, post, patch, delete
like:
app.route('/api/courses/:courseId')
.get(isAuthenticated, courses.read)
also isAuthenticated can be write in another file and use it from your route
Can see this example

Sending back a JSON response when failing Passport.js authentication

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.

Categories