UNPKG

acha-framework

Version:

is a modular framework on both client (angular.js) and server (node.js) side, it provides security, orm, ioc, obfuscation and ...

216 lines 6.95 kB
(function (undefined) { Ioc.define('backend.authentication.errors', [], function (provide) { provide({ USERNAME_DOES_NOT_EXISTS: 0, PASSWORD_WRONG: 1, LOCKED: 2 }); }); Ioc.define('backend.authentication', [ 'backend.configuration', 'backend.orm', 'backend.authentication.errors', 'backend.operationResult', 'backend.localize' ], function (provide, config, database, errors, OperationResult, localize) { const jwt = require('jsonwebtoken'); const passport = require('passport'); const authenticate = function (username, password, done) { const Query = database.models.User.findOne(); Query.where('username', username); Query.run({}, function (err, user) { if (err) { return done(err); } if (!user) { done(null, false, errors.USERNAME_DOES_NOT_EXISTS); return; } if (!user.validatePassword(password)) { done(null, false, errors.PASSWORD_WRONG); return; } if (user.locked) { done(null, false, errors.LOCKED); return; } done(null, user); }); }; const generate_token = function (id) { return { uniqueId: id, token: jwt.sign({ id: id }, config.secret) }; }; const getToken = function (req) { const fromData = req.body.token || req.query.token; const fromHeader = req.headers.token; const fromCookie = req.cookies && req.cookies.token ? req.cookies.token : ''; return fromData || fromHeader || fromCookie; }; const is_user_authenticated = function (req) { return Q.promise(function (resolve, reject) { const token = getToken(req); if (token) { jwt.verify(token, config.secret, function (err, decoded) { if (err) { resolve(false); return; } req.accessToken = decoded; resolve(true); }); return; } resolve(false); }); }; provide({ oauth_google_request: function (req, res, next) { passport.authenticate('google', { session: false, assignProperty: 'oauthAccount', scope: [ 'https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/plus.profile.emails.read' ] })(req, res, next); }, oauth_google_callback: function (req, res, next) { const callback = passport.authenticate('google', { session: false, assignProperty: 'oauthAccount', successRedirect: config.oauth.google.web.success, failureRedirect: config.oauth.google.web.failure }); callback(req, res, function () { const token = generate_token(req.oauthAccount.uniqueId).token; res.cookie('authorization', token); res.redirect(config.oauth.google.web.callback); }); }, authenticate_jwt: function (req, res) { const username = req.body.username || ''; const password = req.body.password || ''; const _errors = {}; if (!username) { _errors.username = ['username is required']; } if (!password) { _errors.password = ['password is required']; } if (!username || !password) { res.json(OperationResult.failed(_errors)); return; } authenticate(username, password, function (err, user, msg) { if (err) { res.json(OperationResult.failed(err)); return; } if (msg !== undefined) { if (msg === errors.USERNAME_DOES_NOT_EXISTS) { _errors.username = ['username does not exist']; } if (msg === errors.LOCKED) { _errors.username = ['account is locked by administrator']; } if (msg === errors.PASSWORD_WRONG) { _errors.password = ['username or password is invalid']; } res.json(OperationResult.failed(_errors)); return; } res.json(OperationResult.success(generate_token(user.uniqueId))); }); }, generate_token: generate_token, verify_jwt: function (req, res, next) { const token = getToken(req); if (token) { jwt.verify(token, config.secret, function (err, decoded) { if (err) { return res.status(401).send(); } else { req.accessToken = decoded; next(); } }); return; } return res.status(401).send(); }, verify_jwt_mvc: function (req, res, next) { const lang = localize.getCulture(req); const redirectUrl = '/' + lang + config.login; is_user_authenticated(req).then(function (result) { if (!result) { return res.redirect(redirectUrl); } next(); }); }, createUserFromOAuth: function (profile, done) { const Query = database.models.User.findOne(); Query.where({ provider: profile.provider, uniqueId: profile.id }); Query.run({}, function (err, user) { if (err) { return done(err); } if (user) { if (user.locked) { done(new Error('account is locked by administrator')); return; } done(null, { id: user.id, uniqueId: user.uniqueId }); return; } user = new database.models.User(); user.provider = profile.provider; switch (profile.provider) { case 'google': user.gender = profile.gender === 'male'; user.email = profile.email; user.username = profile.email.replace('@', '_').replace(/\./g, '_'); user.password = user.email + user.username + profile.id; user.uniqueId = profile.id; break; default: done(new Error('invalid oauth provider')); return; break; } user.isValid(function (isValid) { if (!isValid) { done(new Error('provided data is not sufficient')); return; } user.save(function (err) { if (err) { done(err); return; } done(null, { id: user.id, uniqueId: user.uniqueId }); }); }); }); }, is_authenticated_mvc: function (req, res, next) { is_user_authenticated(req).then(function (result) { req.isAuthenticated = result; next(); }); } }); }); }());