Skip to content
Snippets Groups Projects
Commit fd126b5c authored by Vytor Calixto's avatar Vytor Calixto :space_invader:
Browse files

Add oauth2 authentication

parent e3b7fbf6
No related branches found
No related tags found
2 merge requests!116Release v1.0.0,!73Workerpool feature
Pipeline #
...@@ -23,6 +23,8 @@ const mongoose = require(`${libs}/db/mongoose`); ...@@ -23,6 +23,8 @@ const mongoose = require(`${libs}/db/mongoose`);
const db = mongoose(); const db = mongoose();
require(`${libs}/middlewares/passport`);
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser()); app.use(cookieParser());
...@@ -41,6 +43,9 @@ app.use((req, res, next) => { ...@@ -41,6 +43,9 @@ app.use((req, res, next) => {
}; };
next(); next();
}); });
app.use(passport.initialize());
app.use(passport.session());
app.use((req, res, next) => { app.use((req, res, next) => {
res.setHeader('Last-Modified', (new Date()).toUTCString()); res.setHeader('Last-Modified', (new Date()).toUTCString());
next(); next();
......
...@@ -9,8 +9,8 @@ const log = require(`${libs}/log`)(module); ...@@ -9,8 +9,8 @@ const log = require(`${libs}/log`)(module);
const db = require(`${libs}/db/mongoose`); const db = require(`${libs}/db/mongoose`);
const User = require(`${libs}/models/user`); const User = require(`${libs}/models/user`);
const AccessToken = require(`${libs}/model/accessToken`); const AccessToken = require(`${libs}/models/accessToken`);
const RefreshToken = require(`${libs}/model/refreshToken`); const RefreshToken = require(`${libs}/models/refreshToken`);
// create OAuth 2.0 server // create OAuth 2.0 server
let aserver = oauth2orize.createServer() let aserver = oauth2orize.createServer()
...@@ -27,7 +27,7 @@ let generateTokens = (data, done) => { ...@@ -27,7 +27,7 @@ let generateTokens = (data, done) => {
// curries in `done` callback so we don't need to pass it // curries in `done` callback so we don't need to pass it
let errorHandler = errFn.bind(undefined, done); let errorHandler = errFn.bind(undefined, done);
let refreshToken; let refreshToken;
let refreshTokenValue/ let refreshTokenValue;
let token; let token;
let tokenValue; let tokenValue;
...@@ -47,23 +47,28 @@ let generateTokens = (data, done) => { ...@@ -47,23 +47,28 @@ let generateTokens = (data, done) => {
token.save((err) => { token.save((err) => {
if (err) { if (err) {
console.log('erro aqui?');
log.error(err); log.error(err);
return done(err); return done(err);
} }
done(null, tokenValue, refreshTokenValue, { done(null, tokenValue, refreshTokenValue, {
'expires_in': config.get('security:tokenLife') 'expires_in': config.security.tokenLife
}); });
}) })
}; };
// Exchange username & password for access token. // Exchange username & password for access token.
aserver.exchange(oauth2orize.exchange.password((client, email, password, scope, done) => { aserver.exchange(oauth2orize.exchange.password((client, username, password, scope, done) => {
User.findOne({ email }, (err, user) => { User.findOne({ email: username }, (err, user) => {
if (err) { if (err) {
return done(err); return done(err);
} }
console.log('aqui!');
if (!user || !user.checkPassword(password)) { if (!user || !user.checkPassword(password)) {
console.log('deu ruim');
console.log(user);
console.log(password);
console.log(user.checkPassword(password));
return done(null, false); return done(null, false);
} }
...@@ -71,7 +76,7 @@ aserver.exchange(oauth2orize.exchange.password((client, email, password, scope, ...@@ -71,7 +76,7 @@ aserver.exchange(oauth2orize.exchange.password((client, email, password, scope,
userId: user._id, userId: user._id,
clientId: client._id clientId: client._id
}; };
console.log('gerando token');
generateTokens(model, done); generateTokens(model, done);
}) })
......
...@@ -43,7 +43,7 @@ var UserSchema = new Schema({ ...@@ -43,7 +43,7 @@ var UserSchema = new Schema({
type: String, type: String,
required: [true, 'O campo Função é obrigatório.'] required: [true, 'O campo Função é obrigatório.']
}, },
institution_name: { institutionName: {
type: String, type: String,
required: [true, 'O campo Instituição em que trabalha é obrigatório.'] required: [true, 'O campo Instituição em que trabalha é obrigatório.']
}, },
...@@ -55,7 +55,7 @@ var UserSchema = new Schema({ ...@@ -55,7 +55,7 @@ var UserSchema = new Schema({
type: String, type: String,
required: [true, 'O campo Cidade é obrigatório.'] required: [true, 'O campo Cidade é obrigatório.']
}, },
receive_emails: { receiveEmails: {
type: Boolean type: Boolean
}, },
createdAt: { createdAt: {
...@@ -66,19 +66,27 @@ var UserSchema = new Schema({ ...@@ -66,19 +66,27 @@ var UserSchema = new Schema({
type: String, type: String,
enum: ['LDE', 'SimCAQ'], enum: ['LDE', 'SimCAQ'],
required: true required: true
},
verified: {
type: Boolean,
default: false
} }
}); });
UserSchema.methods.encryptPassword = (password) => { UserSchema.methods.encryptPassword = function(password) {
return crypto.pbkdf2Sync(password, this.salt, 10000, 512); return crypto.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512');
}; };
UserSchema.virtual('password').set((password) => { UserSchema.virtual('password').set(function(password) {
this._plainPassword = password; this._plainPassword = password;
this.salt = crypto.randomBytes(128).toString('hex'); this.salt = crypto.randomBytes(128).toString('hex');
this.hashedPassword = this.encryptPassword(password); this.hashedPassword = this.encryptPassword(password).toString('hex');
}).get(() => { }).get(function() {
return this._plainPassword; return this._plainPassword;
}); });
UserSchema.methods.checkPassword = function(password) {
return this.encryptPassword(password).toString('hex') === this.hashedPassword;
}
module.exports = mongoose.model('User', UserSchema); module.exports = mongoose.model('User', UserSchema);
...@@ -29,7 +29,6 @@ VerificationToken.methods.createVerificationToken = function(done) { ...@@ -29,7 +29,6 @@ VerificationToken.methods.createVerificationToken = function(done) {
verificationToken.set('token', token); verificationToken.set('token', token);
verificationToken.save(function(err) { verificationToken.save(function(err) {
if (err) return done(err); if (err) return done(err);
log.debug('Verification Token', verificationToken);
return done(null, token); return done(null, token);
}) })
} }
......
...@@ -42,6 +42,8 @@ const idhmr = require('./idhmr'); ...@@ -42,6 +42,8 @@ const idhmr = require('./idhmr');
const idhml = require('./idhml'); const idhml = require('./idhml');
const oauth2 = require(`${libs}/middlewares/oauth2`);
api.get('/', (req, res) => { api.get('/', (req, res) => {
res.json({ msg: 'SimCAQ API is running' }); res.json({ msg: 'SimCAQ API is running' });
}); });
...@@ -64,5 +66,6 @@ api.use('/idhme', cache('15 day'), idhme); ...@@ -64,5 +66,6 @@ api.use('/idhme', cache('15 day'), idhme);
api.use('/pibpercapita', cache('1 day'), pibpercapita); api.use('/pibpercapita', cache('1 day'), pibpercapita);
api.use('/population', cache('1 day'), population); api.use('/population', cache('1 day'), population);
api.use('/idhml', cache('1 day'), idhml); api.use('/idhml', cache('1 day'), idhml);
api.use('/auth/token', oauth2.token);
module.exports = api; module.exports = api;
...@@ -10,12 +10,13 @@ const log = require(`${libs}/log`)(module); ...@@ -10,12 +10,13 @@ const log = require(`${libs}/log`)(module);
const User = require(`${libs}/models/user`); const User = require(`${libs}/models/user`);
const jwt = require('jwt-simple'); const VerificationToken = require(`${libs}/models/verificationToken`);
const response = require(`${libs}/middlewares/response`); const response = require(`${libs}/middlewares/response`);
const required_fields = ["email", "password", "name", "cpf", "schooling", "segment", "role", "institution_name", "state", "city"]; const email = require(`${libs}/middlewares/email`);
const passport = require('passport');
function emailSyntax(email) { function emailSyntax(email) {
const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
...@@ -67,51 +68,53 @@ userApp.get('/role', (req, res, next) => { ...@@ -67,51 +68,53 @@ userApp.get('/role', (req, res, next) => {
next(); next();
}, response('role')); }, response('role'));
userApp.post('/', (req, res, next) => { userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => {
if(req.body.email){ User.find((err, users) => {
if(!emailSyntax(req.body.email)){ if(err) {
res.status(400); log.error(err);
res.json({success: false, msg: 'O email informado é inválido.'}); return next(err);
} else {
next();
} }
} else {
let result = [];
users.forEach((user) => {
let u = user.toObject();
delete u.hashedPassword;
delete u.salt;
result.push(u);
});
req.result = result;
next(); next();
}
},
(req, res, next) => {
User.count({'email': req.body.email}, function(err, count){
if (err){
log.error('MongoDB error: ' + err);
res.status(500);
res.json({success: false, msg: ['Um erro ocorreu no banco de dados.']});
}
if(count){
res.status(400);
res.json({success: false, msg: 'O email informado já está cadastrado.'});
} else {
next();
}
}); });
}, response('users'));
}, (req, res, next) => {
User.count({'cpf': req.body.cpf}, function(err, count){ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => {
if (err){ let user = req.user;
log.error('MongoDB error: ' + err); delete user.hashedPassword;
res.status(500); delete user.salt;
res.json({success: false, msg: ['Um erro ocorreu no banco de dados.']}); req.result = user;
}, response('user'));
userApp.get('/:id', (req, res, next) => {
User.findById(req.params.id, (err, user) => {
if(err) {
log.error(err);
return next(err);
} }
if(count){ if(!user) {
res.status(400); req.statusCode = 404;
res.json({success: false, msg: 'O CPF informado já está cadastrado.'}); next({msg: 'User not found'});
} else { } else {
let u = user.toObject;
delete u.hashedPassword;
delete u.salt;
req.result = u;
next(); next();
} }
}); });
}, response('user'));
}, (req, res, next) => { userApp.post('/', (req, res, next) => {
var newUser = new User({ let user = new User({
email: req.body.email, email: req.body.email,
password: req.body.password, password: req.body.password,
name: req.body.name, name: req.body.name,
...@@ -120,73 +123,47 @@ userApp.post('/', (req, res, next) => { ...@@ -120,73 +123,47 @@ userApp.post('/', (req, res, next) => {
course: req.body.course, course: req.body.course,
segment: req.body.segment, segment: req.body.segment,
role: req.body.role, role: req.body.role,
institution_name: req.body.institution_name, institutionName: req.body.institutionName,
state: req.body.state, state: req.body.state,
city: req.body.city, city: req.body.city,
receive_emails: req.body.receive_emails receiveEmails: false || req.body.receiveEmails,
}); origin: req.body.origin
// save the user
newUser.save((err) => {
if (err){
let errArray = [];
let errMsg = '';
for (var e in err.errors) {
errArray.push(err.errors[`${e}`].message);
}
res.status(400);
res.json({success: false, msg: errArray});
}
else {
res.status(201);
res.json({success: true, msg: 'Usuário cadastrado com sucesso!'});
}
}); });
});
userApp.post('/authenticate', (req, res, next) => { user.save((err) => {
if (!req.body.email) { if(err) {
res.status(400); log.error(err);
res.json({success: false, msg: 'O campo Email é obrigatório.'}); return next(err);
} else {
next();
}
}, (req, res, next) => {
if (!req.body.password) {
res.status(400);
res.json({success: false, msg: 'O campo Senha é obrigatório.'});
} else {
next();
}
}, (req, res, next) => {
User.findOne({
email: req.body.email
}, (err, user) => {
if (err) throw err;
if(!user){
res.status(400);
res.json({success: false, msg: ['O Email informado não está cadastrado.']});
} }
else {
user.comparePassword(req.body.password, (err, isMatch) => {
if (isMatch && !err) {
var secret = config.mongodb.secret;
// if user is found and password is right create a token // Create verification token
var token = jwt.encode(user, secret); let verificationToken = new VerificationToken({
userId: user._id
});
//returns user info including token as json verificationToken.createVerificationToken((err, token) => {
res.json({success: true, token: 'JWT ' + token, msg: 'Usuário autenticado com sucesso'}); if(err) {
} log.error(err);
else { return next(err);
res.status(400); }
res.json({success: false, msg: ['A Senha informada é inválida.']}); let text = `Olá, ${user.name}, seja bem vindo ao Laboratório de Dados Educacionais.\n
\nClique neste link para confirmar sua conta: ${req.protocol}://${req.get('host')}/verify/${token}`;
// Send confirmation email
let mailOptions = {
to: `"${user.name} <${user.email}>"`,
subject: "Confirme seu cadastro - Laboratório de Dados Educacionais",
text
}
console.log(mailOptions);
email(mailOptions, (err, info) => {
if(err) {
log.error(err);
return next(err);
} }
log.debug(`Message ${info.messageId} sent: ${info.response}`);
res.json({msg: 'User created'});
}); });
} });
}); });
}); });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment