diff --git a/src/server/app.js b/src/server/app.js index c636e5a3..0d1dd8ea 100755 --- a/src/server/app.js +++ b/src/server/app.js @@ -147,7 +147,7 @@ app.use(express.static(__dirname + '/public')) app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); + res.header("Access-Control-Allow-Headers", "Origin, X-Access-Token, X-Requested-With, Content-Type, Accept"); next(); }); diff --git a/src/server/controllers/index.js b/src/server/controllers/index.js index cd4167b5..43dd6cbf 100755 --- a/src/server/controllers/index.js +++ b/src/server/controllers/index.js @@ -42,6 +42,7 @@ abeExtend.hooks.instance.trigger('beforeAddRoute', router) router.get('/abe/rest/posts*', rest.posts) router.get('/abe/rest/post*', rest.post) router.get('/abe/rest/activity-stream', rest.activityStream) +router.post('/abe/rest/authenticate', rest.authenticate) router.get('/abe/users/forgot', users.getForgot) router.get('/abe/users/list', users.getList) diff --git a/src/server/middlewares/checkCsrf.js b/src/server/middlewares/checkCsrf.js index 7d7ed79c..496ca629 100644 --- a/src/server/middlewares/checkCsrf.js +++ b/src/server/middlewares/checkCsrf.js @@ -2,7 +2,12 @@ var middleware = function(err, req, res, next) { if (err.code !== 'EBADCSRFTOKEN') { return next(err) }else { - if( req.url.indexOf('/abe/users/forgot') > -1 || req.url.indexOf('/abe/users/login') > -1 || !/^\/abe/.test(req.url)) { + if( req.url.indexOf('/abe/users/forgot') > -1 || + req.url.indexOf('/abe/users/login') > -1 || + req.url.indexOf('/abe/rest/authenticate') > -1 || + !/^\/abe/.test(req.url) || + !/^\/abe/.test(req.url) + ) { return next() } } diff --git a/src/server/routes/rest/authenticate.js b/src/server/routes/rest/authenticate.js new file mode 100755 index 00000000..d9306532 --- /dev/null +++ b/src/server/routes/rest/authenticate.js @@ -0,0 +1,83 @@ +import Cookies from 'cookies' +import moment from 'moment' +import Strategy from 'passport-local' +import passport from 'passport' +import jwt from 'jwt-simple' + +import { + config, + User +} from '../../../cli' + +/** + * Strategy + */ +passport.use(new Strategy( + function(username, password, done) { + User.utils.findByUsername(username, function(err, user) { + if (err) { return done(err) } + if (!user) { return done(null, false, { message: 'Incorrect username or password.' }) } + if(!User.utils.isValid(user, password)) { + return done(null, false, { message: 'Incorrect username or password.' }) + } + return done(null, user) + }) + } +)) + +passport.serializeUser(function(user, done) { + done(null, user.id) +}) + +passport.deserializeUser(function(id, done) { + User.utils.find(id, function (err, user) { + done(err, user) + }) +}) + +var route = function(req, res, next) { + User.utils.loginLimitTry(req.body.username) + .then((limit) => { + if (limit != null) { + // all good + if (!limit.remaining) { + req.flash('info', 'Rate limit exceeded') + return res.status(401).json({ error: info }); + } + } + + passport.authenticate( + 'local', + { session: false}, + function(err, user, info) { + var secret = config.users.secret + if (err) { return next(err) } + + if (!user) { + req.flash('info', info.message) + //return res.redirect('/abe/users/login') + return res.status(401).json({ error: info }); + } + var expires = moment().add(7, 'days').valueOf() + var token = jwt.encode({ + iss: user.id, + exp: expires, + username: user.username, + name: user.name, + email: user.email, + role: user.role + }, secret) + + var cookies = new Cookies( req, res, { + secure: config.cookie.secure + }) + cookies.set( 'x-access-token', token ) + + var result = {} + res.set('Content-Type', 'application/json') + res.send(JSON.stringify(result)) + })(req, res, next) + }) +} + +export default route \ No newline at end of file diff --git a/src/server/routes/rest/index.js b/src/server/routes/rest/index.js index 2bdeb24b..ac4dc5b9 100644 --- a/src/server/routes/rest/index.js +++ b/src/server/routes/rest/index.js @@ -1,9 +1,11 @@ import post from './post' import posts from './posts' import activityStream from './activity-stream' +import authenticate from './authenticate' export { post, posts, - activityStream + activityStream, + authenticate } \ No newline at end of file