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
JavaScript
(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();
});
}
});
});
}());