diff --git a/config.json.example b/config.json.example
index d2ecb4ba1f6c7bed2c9c1dbba6c900345d64f310..5a96ebdd463c1d95a4002864095dcaf0b2c41d1d 100644
--- a/config.json.example
+++ b/config.json.example
@@ -16,8 +16,7 @@
             "url": "http://simcaqdb3.c3sl.ufpr.br:3000"
         },
         "mongodb" : {
-            "uri": "mongodb://localhost/dev_users",
-            "secret": "SimCAQC3SL"
+            "uri": "mongodb://localhost/dev_users"
         },
         "monq": {
             "uri": "mongodb://localhost/dev_monq"
@@ -25,6 +24,12 @@
         "default": {
             "api": {
                 "version" : "v1"
+            },
+            "lde": {
+                "url": "http://ldedev.c3sl.ufpr.br/#"
+            },
+            "simcaq": {
+                "url": "http://simcaqdev.c3sl.ufpr.br/#"
             }
         },
         "email": {
@@ -33,11 +38,14 @@
             "secure": false,
             "ignoreTLS": true,
             "from": "\"Laboratório de Dados Educacionais\" <lde@c3sl.ufpr.br>"
+        },
+        "security": {
+            "tokenLife": 3600
         }
     },
     "test":
     {
-        "port": 3000,
+        "port": 4000,
         "ip": "127.0.0.1",
         "debug" : true,
         "monetdb": {
@@ -61,13 +69,28 @@
         "default": {
             "api": {
                 "version" : "v1"
+            },
+            "lde": {
+                "url": "http://ldedev.c3sl.ufpr.br/#"
+            },
+            "simcaq": {
+                "url": "http://simcaqdev.c3sl.ufpr.br/#"
             }
         },
-        "email": "simcaq@c3sl.ufpr.br"
+        "email": {
+            "port": 25,
+            "host": "mx.c3sl.ufpr.br",
+            "secure": false,
+            "ignoreTLS": true,
+            "from": "\"Laboratório de Dados Educacionais\" <lde@c3sl.ufpr.br>"
+        },
+        "security": {
+            "tokenLife": 3600
+        }
     },
     "production":
     {
-        "port": 3000,
+        "port": 6000,
         "ip": "127.0.0.1",
         "debug" : false,
         "monetdb": {
@@ -91,8 +114,23 @@
         "default": {
             "api": {
                 "version" : "v1"
+            },
+            "lde": {
+                "url": "http://lde.c3sl.ufpr.br/#"
+            },
+            "simcaq": {
+                "url": "http://simcaq.c3sl.ufpr.br/#"
             }
         },
-        "email": "simcaq@c3sl.ufpr.br"
+        "email": {
+            "port": 25,
+            "host": "mx.c3sl.ufpr.br",
+            "secure": false,
+            "ignoreTLS": true,
+            "from": "\"Laboratório de Dados Educacionais\" <lde@c3sl.ufpr.br>"
+        },
+        "security": {
+            "tokenLife": 3600
+        }
     }
 }
diff --git a/package.json b/package.json
index 05fe1eae53edec73f2feeae28535f9cb3389b347..65e8d4c96f3372c0348376b054012ae247d64202 100644
--- a/package.json
+++ b/package.json
@@ -36,9 +36,13 @@
     "monetdb-pool": "0.0.8",
     "mongoose": "^4.6.0",
     "nconf": "^0.8.x",
+    "node-uuid": "^1.4.8",
     "nodemailer": "^4.0.1",
     "nodemailer-html-to-text": "^2.1.0",
+    "oauth2orize": "^1.8.1",
     "passport": "^0.3.2",
+    "passport-http-bearer": "^1.0.1",
+    "passport-oauth2-client-password": "^0.1.2",
     "request": "^2.81.0",
     "squel": "^5.4.2",
     "winston": "^2.2.0"
diff --git a/src/libs/app.js b/src/libs/app.js
index 662b3e9d21e8c328bf6efef8e700ee00c16f8765..4dff1ee930bde49cfbd47a925b23ebf5b9847041 100644
--- a/src/libs/app.js
+++ b/src/libs/app.js
@@ -23,6 +23,8 @@ const mongoose = require(`${libs}/db/mongoose`);
 
 const db = mongoose();
 
+require(`${libs}/middlewares/passport`);
+
 app.use(bodyParser.json());
 app.use(bodyParser.urlencoded({ extended: false }));
 app.use(cookieParser());
@@ -41,6 +43,9 @@ app.use((req, res, next) => {
     };
     next();
 });
+app.use(passport.initialize());
+app.use(passport.session());
+
 app.use((req, res, next) => {
     res.setHeader('Last-Modified', (new Date()).toUTCString());
     next();
diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0f4a9ccd7022237397a7d783604894327627c24
--- /dev/null
+++ b/src/libs/middlewares/oauth2.js
@@ -0,0 +1,126 @@
+const oauth2orize = require('oauth2orize');
+const passport = require('passport');
+const crypto = require('crypto');
+
+const libs = `${process.cwd()}/libs`;
+
+const config = require(`${libs}/config`);
+const log = require(`${libs}/log`)(module);
+
+const db = require(`${libs}/db/mongoose`);
+const User = require(`${libs}/models/user`);
+const AccessToken = require(`${libs}/models/accessToken`);
+const RefreshToken = require(`${libs}/models/refreshToken`);
+
+// create OAuth 2.0 server
+let aserver = oauth2orize.createServer()
+
+// Generic error handler
+let errFn = (cb, err) => {
+    if (err) {
+        return cb(err)
+    }
+}
+
+// Destroys any old tokens and generates a new access and refresh token
+let generateTokens = (data, done) => {
+    // curries in `done` callback so we don't need to pass it
+    let errorHandler = errFn.bind(undefined, done);
+    let refreshToken;
+    let refreshTokenValue;
+    let token;
+    let tokenValue;
+
+    RefreshToken.remove(data, errorHandler);
+    AccessToken.remove(data, errorHandler);
+
+    tokenValue = crypto.randomBytes(32).toString('hex');
+    refreshTokenValue = crypto.randomBytes(32).toString('hex');
+
+    data.token = tokenValue;
+    token = new AccessToken(data);
+
+    data.token = refreshTokenValue;
+    refreshToken = new RefreshToken(data);
+
+    refreshToken.save(errorHandler);
+
+    token.save((err) => {
+        if (err) {
+            console.log('erro aqui?');
+            log.error(err);
+            return done(err);
+        }
+        done(null, tokenValue, refreshTokenValue, {
+            'expires_in': config.security.tokenLife
+        });
+    })
+};
+
+// Exchange username & password for access token.
+aserver.exchange(oauth2orize.exchange.password((client, username, password, scope, done) => {
+    User.findOne({ email: username }, (err, user) => {
+        if (err) {
+            return done(err);
+        }
+        console.log('aqui!');
+        if (!user || !user.checkPassword(password)) {
+            console.log('deu ruim');
+            console.log(user);
+            console.log(password);
+            if(user) console.log(user.checkPassword(password));
+            return done(null, false);
+        }
+
+        var model = {
+            userId: user._id,
+            clientId: client._id
+        };
+        console.log('gerando token');
+        generateTokens(model, done);
+    })
+
+}));
+
+// Exchange refreshToken for access token.
+aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, done)  =>{
+    RefreshToken.findOne({ token: refreshToken, clientId: client._id }, (err, token) => {
+        if (err) {
+            return done(err);
+        }
+
+        if (!token) {
+            return done(null, false);
+        }
+
+        User.findById(token.userId, (err, user)  => {
+            if (err) { 
+                log.error(err);
+                return done(err);
+            }
+            if (!user) { 
+                return done(null, false); 
+            }
+
+            var model = {
+                userId: user._id,
+                clientId: client._id
+            };
+
+            generateTokens(model, done);
+        })
+    })
+}))
+
+// token endpoint
+//
+// `token` middleware handles client requests to exchange authorization grants
+// for access tokens.  Based on the grant type being exchanged, the above
+// exchange middleware will be invoked to handle the request.  Clients must
+// authenticate when making requests to this endpoint.
+
+exports.token = [
+    passport.authenticate(['oauth2-client-password'], { session: false }),
+    aserver.token(),
+    aserver.errorHandler()
+];
diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js
index c939926099b845b641268d66e9d2bccf9085a043..91b2b22a13df537fcf98030379482422f3fc880d 100644
--- a/src/libs/middlewares/passport.js
+++ b/src/libs/middlewares/passport.js
@@ -1,54 +1,67 @@
-const JwtStrategy = require('passport-jwt').Strategy;
-const ExtractJwt = require('passport-jwt').ExtractJwt;
+const passport = require('passport');
+const ClientPasswordStrategy = require('passport-oauth2-client-password');
+const BearerStrategy = require('passport-http-bearer').Strategy;
+
 const libs = `${process.cwd()}/libs`;
 const config = require(`${libs}/config`);
-const User = require(`${libs}/models/user`)
-
-module.exports = function(passport){
-    var opts = {};
-    opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
-    opts.secretOrKey = config.get('mongodb:secret');
-    passport.use(new JwtStrategy(opts, function(jwt_payload, done){
-        User.find({email: jwt_payload.email}, function(err, user){
+
+const User = require(`${libs}/models/user`);
+const Client = require(`${libs}/models/client`);
+const AccessToken = require(`${libs}/models/accessToken`);
+const RefreshToken = require(`${libs}/models/refreshToken`);
+const email = require(`${libs}/middlewares/email`);
+
+passport.use(new ClientPasswordStrategy( (clientId, clientSecret, done) => {
+        Client.findOne({ _id: clientId }, (err, client) => {
             if (err) {
                 return done(err);
             }
 
-            if (!user) {
-                return done(null, false, {message: 'Unknown user'});
+            if (!client) {
+                return done(null, false);
             }
 
-            return done(null, user);
-        });
-    }));
-};
+            if (client.clientSecret !== clientSecret) {
+                return done(null, false);
+            }
 
-/* To check if a user has access to a route, one must use passport.authenticate() specifying 'JWT' as the strategy in the route declaration, like so:
-//pass passportfor configuration
-require('./config/passport')(passport);
+            return done(null, client);
+        })
+    }
+));
 
-app.post('/route', passport.authenticate('jwt', { session: false}), function(req, res) { });
+passport.use(new BearerStrategy( (accessToken, done) => {
+        AccessToken.findOne({ token: accessToken }, (err, token) => {
+            if (err) {
+                return done(err);
+            }
+
+            if (!token) {
+                return done(null, false);
+            }
+
+            if( Math.round((Date.now()-token.created)/1000) > config.get('security:tokenLife') ) {
+                AccessToken.remove({ token: accessToken }, (err) => {
+                    if (err) {
+                        return done(err);
+                    }
+                });
+
+                return done(null, false, { msg: 'Token expired' });
+            }
 
-the user object is then accessible via req.user
-----
+            Usuario.findById(token.userId, function(err, usuario) {
+                if (err) {
+                    return done(err);
+                }
 
-Another way to check if a user is authenticated, is to check the request header for the json web token, like so:
+                if (!usuario) {
+                    return done(null, false, { msg: 'Unknown user' });
+                }
 
-getToken = function (headers) {
-  if (headers && headers.authorization) {
-    var parted = headers.authorization.split(' ');
-    if (parted.length === 2) {
-      return parted[1];
-    } else {
-      return null;
+                var info = { scope: '*' };
+                done(null, usuario, info);
+            })
+        })
     }
-  } else {
-    return null;
-  }
-};
-
-var token = getToken(req.headers);
-  if (token) {
-    var decoded = jwt.decode(token, config.get(mongodb.secret));
-  }
- */
+));
diff --git a/src/libs/models/accessToken.js b/src/libs/models/accessToken.js
new file mode 100644
index 0000000000000000000000000000000000000000..daab5898a66b952f72359d9685e951b1acf980b7
--- /dev/null
+++ b/src/libs/models/accessToken.js
@@ -0,0 +1,29 @@
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const libs = `${process.cwd()}/libs`;
+const User = require(`${libs}/models/user`);
+const Client = require(`${libs}/models/client`);
+
+let AccessToken = new Schema({
+    userId: {
+        type: Schema.Types.ObjectId,
+        required: true,
+        ref: 'User'
+    },
+    clientId: {
+        type: Schema.Types.ObjectId,
+        required: true,
+        ref: 'Client'
+    },
+    token: {
+        type: String,
+        unique: true,
+        required: true
+    },
+    createdAt: {
+        type: Date,
+        default: Date.now
+    }
+});
+
+module.exports = mongoose.model('AccessToken', AccessToken);
diff --git a/src/libs/models/client.js b/src/libs/models/client.js
new file mode 100644
index 0000000000000000000000000000000000000000..8ac80d8d158705f63efbbecc72de37d1fef6a3ac
--- /dev/null
+++ b/src/libs/models/client.js
@@ -0,0 +1,17 @@
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+
+let Client = new Schema({
+    name: {
+        type: String,
+        unique: true,
+        required: true
+    },
+    clientSecret: {
+        type: String,
+        required: true,
+        unique: true
+    }
+});
+
+module.exports = mongoose.model('Client', Client);
diff --git a/src/libs/models/refreshToken.js b/src/libs/models/refreshToken.js
new file mode 100644
index 0000000000000000000000000000000000000000..c5f8fd63cdd30733bb60f341e6617420d945b037
--- /dev/null
+++ b/src/libs/models/refreshToken.js
@@ -0,0 +1,30 @@
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const libs = `${process.cwd()}/libs`;
+const User = require(`${libs}/models/user`);
+const Client = require(`${libs}/models/client`);
+
+let RefreshToken = new Schema({
+    userId: {
+        type: Schema.Types.ObjectId,
+        required: true,
+        ref: 'User'
+    },
+    clientId: {
+        type: Schema.Types.ObjectId,
+        required: true,
+        ref: 'Client'
+    },
+    token: {
+        type: String,
+        unique: true,
+        required: true
+    },
+    createdAt: {
+        type: Date,
+        default: Date.now
+    }
+});
+
+module.exports = mongoose.model('RefreshToken', RefreshToken);
+
diff --git a/src/libs/models/user.js b/src/libs/models/user.js
index 9b9c2fa5c70bafd507f0a60a062b80efe45b4d13..47c7c65e5f35f42fcdf6b394767d74b3e1453965 100644
--- a/src/libs/models/user.js
+++ b/src/libs/models/user.js
@@ -1,5 +1,5 @@
 const mongoose = require('mongoose');
-const bcrypt = require('bcrypt-nodejs');
+const crypto = require('crypto')
 const libs = `${process.cwd()}/libs`;
 const log = require(`${libs}/log`)(module);
 const Schema = mongoose.Schema;
@@ -11,7 +11,7 @@ var UserSchema = new Schema({
         unique: true,
         required: [true, 'O campo Email é obrigatório.']
     },
-    password: {
+    hashedPassword: {
         type: String,
         required: [true, 'O campo Senha é obrigatório.']
     },
@@ -39,7 +39,7 @@ var UserSchema = new Schema({
         type: String,
         required: [true, 'O campo Função é obrigatório.']
     },
-    institution_name: {
+    institutionName: {
         type: String,
         required: [true, 'O campo Instituição em que trabalha é obrigatório.']
     },
@@ -51,39 +51,38 @@ var UserSchema = new Schema({
         type: String,
         required: [true, 'O campo Cidade é obrigatório.']
     },
-    receive_emails: {
+    receiveEmails: {
         type: Boolean
+    },
+    createdAt: {
+        type: Date,
+        default: Date.now
+    },
+    origin: {
+        type: String,
+        enum: ['LDE', 'SimCAQ'],
+        required: true
+    },
+    verified: {
+        type: Boolean,
+        default: false
     }
-
 });
 
-UserSchema.pre('save', function (next) {
-    var user = this;
-    if (this.isModified('password') || this.isNew) {
-        bcrypt.genSalt(10, function (err, salt) {
-            if (err) {
-                return next(err);
-            }
-            bcrypt.hash(user.password, salt, null, function (err, hash) {
-                if (err) {
-                    return next(err);
-                }
-                user.password = hash;
-                next();
-            });
-        });
-    } else {
-        return next();
-    }
+UserSchema.methods.encryptPassword = function(password) {
+    return crypto.pbkdf2Sync(password, this.salt, 10000, 512, 'sha512');
+};
+
+UserSchema.virtual('password').set(function(password) {
+    this._plainPassword = password;
+    this.salt = crypto.randomBytes(128).toString('hex');
+    this.hashedPassword = this.encryptPassword(password).toString('hex');
+}).get(function() {
+    return this._plainPassword;
 });
 
-UserSchema.methods.comparePassword = function (passw, cb) {
-    bcrypt.compare(passw, this.password, function (err, isMatch) {
-        if (err) {
-            return cb(err);
-        }
-        cb(null, isMatch);
-    });
-};
+UserSchema.methods.checkPassword = function(password) {
+    return this.encryptPassword(password).toString('hex') === this.hashedPassword;
+}
 
 module.exports = mongoose.model('User', UserSchema);
diff --git a/src/libs/models/verificationToken.js b/src/libs/models/verificationToken.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef7e109e16364874ea7d3f4b07b6e19ce74c3eae
--- /dev/null
+++ b/src/libs/models/verificationToken.js
@@ -0,0 +1,41 @@
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const libs = `${process.cwd()}/libs`;
+const log = require(`${libs}/log`)(module);
+const User = require(`${libs}/models/user`);
+const uuid = require('node-uuid');
+
+let VerificationToken = new Schema({
+    userId: {
+        type: Schema.Types.ObjectId,
+        required: true,
+        ref: 'User'
+    },
+    token: {
+        type: String,
+        required: true
+    },
+    verified: {
+        type: Boolean,
+        required: true,
+        default: false
+    },
+    createdAt: {
+        type: Date,
+        required: true,
+        default: Date.now
+    }
+});
+
+VerificationToken.methods.createVerificationToken = function(done) {
+    let verificationToken = this;
+    let token = uuid.v4();
+    verificationToken.set('token', token);
+    verificationToken.verified = false;
+    verificationToken.save(function(err) {
+        if (err) return done(err);
+        return done(null, token);
+    })
+}
+
+module.exports = mongoose.model('VerificationToken', VerificationToken);
diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js
index 7353dfd144c09add582aab1262ee8e29248c39a2..609a2ad326a6dbd8609b3c68923eee61263f8993 100644
--- a/src/libs/routes/api.js
+++ b/src/libs/routes/api.js
@@ -8,8 +8,6 @@ const config = require(`${libs}/config`);
 
 const classes = require('./class');
 
-const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
-
 const enrollment = require('./enrollment');
 
 const state = require('./state');
@@ -42,6 +40,10 @@ const idhmr = require('./idhmr');
 
 const idhml = require('./idhml');
 
+const oauth2 = require(`${libs}/middlewares/oauth2`);
+
+const verifyToken = require(`${libs}/routes/verifyToken`);
+
 api.get('/', (req, res) => {
     res.json({ msg: 'SimCAQ API is running' });
 });
@@ -49,20 +51,22 @@ api.get('/', (req, res) => {
 // mount API routes
 api.use('/user', user);
 api.use('/simulation', simulation);
-api.use('/class', cache('15 day'), classes);
-api.use('/enrollment', cache('1 day'), enrollment);
-api.use('/state', cache('15 day'), state);
-api.use('/region', cache('15 day'), region);
-api.use('/city', cache('15 day'), city);
-api.use('/school', cache('15 day'), school);
-api.use('/spatial', cache('1 day'), spatial);
-api.use('/classroom', cache('15 day'), classroom);
-api.use('/teacher', cache('1 day'), teacher);
-api.use('/idhmr', cache('1 day'), idhmr);
-api.use('/idhm', cache('1 day'), idhm);
-api.use('/idhme', cache('15 day'), idhme);
-api.use('/pibpercapita', cache('1 day'), pibpercapita);
-api.use('/population', cache('1 day'), population);
-api.use('/idhml', cache('1 day'), idhml);
+api.use('/class', classes);
+api.use('/enrollment', enrollment);
+api.use('/state', state);
+api.use('/region', region);
+api.use('/city', city);
+api.use('/school', school);
+api.use('/spatial', spatial);
+api.use('/classroom', classroom);
+api.use('/teacher', teacher);
+api.use('/idhmr', idhmr);
+api.use('/idhm', idhm);
+api.use('/idhme', idhme);
+api.use('/pibpercapita', pibpercapita);
+api.use('/population', population);
+api.use('/idhml', idhml);
+api.use('/auth/token', oauth2.token);
+api.use('/verify', verifyToken);
 
 module.exports = api;
diff --git a/src/libs/routes/city.js b/src/libs/routes/city.js
index b7999a8ef9e35fa7fd8011ae73c2149f2d4d02e3..65fba27ea92db049f156a196b7fdbd2da0fc0756 100644
--- a/src/libs/routes/city.js
+++ b/src/libs/routes/city.js
@@ -12,8 +12,14 @@ const response = require(`${libs}/middlewares/response`);
 
 const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+cityApp.use(cache('15 day'));
+
 rqf.addField({
     name: 'filter',
     field: false,
diff --git a/src/libs/routes/class.js b/src/libs/routes/class.js
index 8dde3a491f2027ea86f97d960686e8fb07c5b186..70e5185e5b205582ebf5aaa8d5c54141464c15c0 100644
--- a/src/libs/routes/class.js
+++ b/src/libs/routes/class.js
@@ -16,7 +16,14 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqfCount = new ReqQueryFields();
+
+classApp.use(cache('15 day'));
+
 // Complete range of the enrollments dataset.
 // Returns a tuple of start and ending years of the complete enrollments dataset.
 classApp.get('/year_range', (req, res, next) => {
diff --git a/src/libs/routes/classroom.js b/src/libs/routes/classroom.js
index 3658a587167c24cc3a3afcc37e0dde4b4808a2ba..75794c86ac4e8b7d556289bcd927baf3d54b1313 100644
--- a/src/libs/routes/classroom.js
+++ b/src/libs/routes/classroom.js
@@ -14,6 +14,10 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
 let rqfCount = new ReqQueryFields();
@@ -188,7 +192,7 @@ rqf.addField({
     }
 });
 
-classroomApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
+classroomApp.get('/', cache('15 day'), rqf.parse(), rqf.build(), (req, res, next) => {
     req.sql.from('escola')
         .field('SUM(escola.num_salas)', 'total')
         .field("'Brasil'", 'name')
diff --git a/src/libs/routes/enrollment.js b/src/libs/routes/enrollment.js
index a8523ba967de2296e86297e5bb52500eae2cc63d..a5feaac39f5fcc0365bba527fc2f8156fa94c1d7 100644
--- a/src/libs/routes/enrollment.js
+++ b/src/libs/routes/enrollment.js
@@ -16,6 +16,12 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
+enrollmentApp.use(cache('15 day'));
+
 let rqf = new ReqQueryFields();
 
 // Complete range of the enrollments dataset.
diff --git a/src/libs/routes/idhm.js b/src/libs/routes/idhm.js
index 51620254d30551f846fe735bd15a8d6f99a1a3fb..f9336c5a256235ddb3dd7a4a68a7c920ba43066d 100644
--- a/src/libs/routes/idhm.js
+++ b/src/libs/routes/idhm.js
@@ -16,8 +16,14 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+idhmApp.use(cache('15 day'));
+
 idhmApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
diff --git a/src/libs/routes/idhme.js b/src/libs/routes/idhme.js
index 9b4672efe4f50be75866c2169422afeb9ed509af..22ef5697dbbcfdba5a7f829a206177731367e232 100644
--- a/src/libs/routes/idhme.js
+++ b/src/libs/routes/idhme.js
@@ -14,8 +14,14 @@ const id2str = require(`${libs}/middlewares/id2str`);
 
 const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+idhmeApp.use(cache('15 day'));
+
 idhmeApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
diff --git a/src/libs/routes/idhml.js b/src/libs/routes/idhml.js
index a24c51ccbfe0f0f108cb554f224aa12e5ecf7f42..8d9e2e77014913ad902980244f2c1e3808cc513e 100644
--- a/src/libs/routes/idhml.js
+++ b/src/libs/routes/idhml.js
@@ -14,8 +14,14 @@ const id2str = require(`${libs}/middlewares/id2str`);
 
 const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+idhmlApp.use(cache('15 day'));
+
 idhmlApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
diff --git a/src/libs/routes/idhmr.js b/src/libs/routes/idhmr.js
index df8847bcd1d6e588044e5920d9796ebe3b783d39..33f950dc09e46efd41ef086738c0c237a6f018fa 100644
--- a/src/libs/routes/idhmr.js
+++ b/src/libs/routes/idhmr.js
@@ -16,8 +16,14 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+idhmrApp.use(cache('15 day'));
+
 idhmrApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
diff --git a/src/libs/routes/pibpercapita.js b/src/libs/routes/pibpercapita.js
index 1821ae83b57b9e984b54c8b3ab3aa6e78a7a0bbf..d8b7f37b1f0338b0e2a88875f7f90ae20f3c371b 100644
--- a/src/libs/routes/pibpercapita.js
+++ b/src/libs/routes/pibpercapita.js
@@ -16,8 +16,14 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+pibpercapitaApp.use(cache('15 day'));
+
 pibpercapitaApp.get('/year_range', (req, res, next) => {
     req.sql.from('ibge_pib')
     .field('MIN(ibge_pib.ano_censo)', 'start_year')
diff --git a/src/libs/routes/population.js b/src/libs/routes/population.js
index 3d05c3d0d06fd1630bdcf86df75ec4fba05eaa01..4c90963a60fb28ec5e7732ba93e68a67a4c7224d 100644
--- a/src/libs/routes/population.js
+++ b/src/libs/routes/population.js
@@ -16,8 +16,14 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+populationApp.use(cache('15 day'));
+
 populationApp.get('/year_range', (req, res, next) => {
     req.sql.from('ibge_populacao')
     .field('MIN(ibge_populacao.ano_censo)', 'start_year')
diff --git a/src/libs/routes/region.js b/src/libs/routes/region.js
index 0afacc0a54ca9421b9ef724515f55f508ee99077..81f655c39bd45836bc39cdfe2a865fd9fbf5517d 100644
--- a/src/libs/routes/region.js
+++ b/src/libs/routes/region.js
@@ -14,8 +14,14 @@ const response = require(`${libs}/middlewares/response`);
 
 const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+regionApp.use(cache('15 day'));
+
 rqf.addField({
     name: 'filter',
     field: false,
diff --git a/src/libs/routes/school.js b/src/libs/routes/school.js
index 6f13b95bccd298fc2a93c1965970e7b27296afdb..47d6a1407bd7b7dd70f6e93cd9b985cea9b5f024 100644
--- a/src/libs/routes/school.js
+++ b/src/libs/routes/school.js
@@ -16,24 +16,28 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const request = require(`request`);
 
+const config = require(`${libs}/config`);
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 let rqfCount = new ReqQueryFields();
 
 // Return location
-schoolApp.get('/year_range', (req, res, next) => {
+schoolApp.get('/year_range', cache('15 day'), (req, res, next) => {
     req.sql.from('escola')
     .field('MIN(escola.ano_censo)', 'start_year')
     .field('MAX(escola.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
-schoolApp.get('/years', (req, res, next) => {
+schoolApp.get('/years', cache('15 day'), (req, res, next) => {
     req.sql.from('escola').
     field('DISTINCT escola.ano_censo', 'year');
     next();
 }, query, response('years'));
 
-schoolApp.get('/location', (req, res, next) => {
+schoolApp.get('/location', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: 1, name: 'Urbana'},
         {id: 2, name: 'Rural'}
@@ -49,14 +53,14 @@ schoolApp.get('/adm_dependency', (req, res, next) => {
     next();
 }, query, response('adm_dependency'));
 
-schoolApp.get('/adm_dependency_detailed', (req, res, next) => {
+schoolApp.get('/adm_dependency_detailed', cache('15 day'), (req, res, next) => {
     req.sql.from('dependencia_adm_priv')
     .field('id', 'id')
     .field('nome', 'name');
     next();
 }, query, response('adm_dependency_detailed'));
 
-schoolApp.get('/government_agreement', (req, res, next) => {
+schoolApp.get('/government_agreement', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -65,7 +69,7 @@ schoolApp.get('/government_agreement', (req, res, next) => {
     next();
 }, response('government_agreement'));
 
-schoolApp.get('/agreement', (req, res, next) => {
+schoolApp.get('/agreement', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: 1, name: 'Municipal'},
         {id: 2, name: 'Estadual'},
@@ -83,7 +87,7 @@ schoolApp.get('/education_day_care_child', (req, res, next) => {
     next();
 }, response('education_day_care_child'));
 
-schoolApp.get('/education_preschool_child', (req, res, next) => {
+schoolApp.get('/education_preschool_child', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -92,7 +96,7 @@ schoolApp.get('/education_preschool_child', (req, res, next) => {
     next();
 }, response('education_preschool_child'));
 
-schoolApp.get('/education_begin_elementary_school', (req, res, next) => {
+schoolApp.get('/education_begin_elementary_school', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -101,7 +105,7 @@ schoolApp.get('/education_begin_elementary_school', (req, res, next) => {
     next();
 }, response('education_begin_elementary_school'));
 
-schoolApp.get('/education_end_elementary_school', (req, res, next) => {
+schoolApp.get('/education_end_elementary_school', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -110,7 +114,7 @@ schoolApp.get('/education_end_elementary_school', (req, res, next) => {
     next();
 }, response('education_end_elementary_school'));
 
-schoolApp.get('/education_middle_school', (req, res, next) => {
+schoolApp.get('/education_middle_school', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -119,7 +123,7 @@ schoolApp.get('/education_middle_school', (req, res, next) => {
     next();
 }, response('education_middle_school'));
 
-schoolApp.get('/education_professional', (req, res, next) => {
+schoolApp.get('/education_professional', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -128,7 +132,7 @@ schoolApp.get('/education_professional', (req, res, next) => {
     next();
 }, response('education_professional'));
 
-schoolApp.get('/education_eja', (req, res, next) => {
+schoolApp.get('/education_eja', cache('15 day'), (req, res, next) => {
     req.result = [
         {id: null, name: 'Não Declarado'},
         {id: 0, name: 'Não'},
@@ -444,7 +448,7 @@ schoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
     next();
 }, query, response('school'));
 
-schoolApp.get('/count', rqfCount.parse(), rqfCount.build(), (req, res, next) => {
+schoolApp.get('/count', cache('15 day'), rqfCount.parse(), rqfCount.build(), (req, res, next) => {
 
     req.sql.from('escola')
         .field('COUNT(escola.id)', 'total')
@@ -457,13 +461,17 @@ schoolApp.get('/count', rqfCount.parse(), rqfCount.build(), (req, res, next) =>
 }, query, id2str.transform(), response('school'));
 
 schoolApp.get('/download', rqf.parse(), rqf.build(), (req, res, next) => {
+    let username = req.query.user;
+    let email = req.query.email;
+
     req.sql.from('escola')
     .field('*');
-    // agenda.now('download database', {sql: req.sql.toString(), table: req.sql.tableFrom});
     let form = {
         query: req.sql.toString(),
         table: req.sql.tableFrom,
-        name: req.sql.tableFrom
+        name: req.sql.tableFrom,
+        username,
+        email
     };
     request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => {
         if(err) {
diff --git a/src/libs/routes/state.js b/src/libs/routes/state.js
index 2663fe9890849aea38ae51244e330454983a3742..67bdfc1bfe86f6976d5af8bf6a31e32ac9dc997b 100644
--- a/src/libs/routes/state.js
+++ b/src/libs/routes/state.js
@@ -12,8 +12,14 @@ const response = require(`${libs}/middlewares/response`);
 
 const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
 let rqf = new ReqQueryFields();
 
+stateApp.use(cache('15 day'));
+
 rqf.addField({
     name: 'filter',
     field: false,
diff --git a/src/libs/routes/teacher.js b/src/libs/routes/teacher.js
index 294417dd1af605ae7a17a64d504269209121acd1..4ca0b6b43cfff4c8ec3ac7323eeec3442079d1f4 100644
--- a/src/libs/routes/teacher.js
+++ b/src/libs/routes/teacher.js
@@ -16,8 +16,14 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]}  }).middleware;
+
 let rqf = new ReqQueryFields();
 
+teacherApp.use(cache('15 day'));
+
 // Returns a tuple of start and ending years of the complete enrollments dataset.
 teacherApp.get('/year_range', (req, res, next) => {
     req.sql.from('docente')
diff --git a/src/libs/routes/user.js b/src/libs/routes/user.js
index 0d04dfd0f799bbda44eb0dfccc5d9f5ea42f7fcd..f22f356a58c3e0eb62d4d1b19358a40eed7d5718 100644
--- a/src/libs/routes/user.js
+++ b/src/libs/routes/user.js
@@ -10,12 +10,13 @@ const log = require(`${libs}/log`)(module);
 
 const User = require(`${libs}/models/user`);
 
-const jwt = require('jwt-simple');
+const VerificationToken = require(`${libs}/models/verificationToken`);
 
 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) {
     const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
@@ -67,51 +68,53 @@ userApp.get('/role', (req, res, next) => {
     next();
 }, response('role'));
 
-userApp.post('/', (req, res, next) => {
-    if(req.body.email){
-        if(!emailSyntax(req.body.email)){
-            res.status(400);
-            res.json({success: false, msg: 'O email informado é inválido.'});
-        } else {
-            next();
+userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => {
+    User.find((err, users) => {
+        if(err) {
+            log.error(err);
+            return next(err);
         }
-    } else {
+
+        let result = [];
+        users.forEach((user) => {
+            let u = user.toObject();
+            delete u.hashedPassword;
+            delete u.salt;
+            result.push(u);
+        });
+        req.result = result;
         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();
-        }
     });
-
-}, (req, res, next) => {
-    User.count({'cpf': req.body.cpf}, 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.']});
+}, response('users'));
+
+userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => {
+    let user = req.user;
+    delete user.hashedPassword;
+    delete user.salt;
+    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){
-            res.status(400);
-            res.json({success: false, msg: 'O CPF informado já está cadastrado.'});
-
+        if(!user) {
+            req.statusCode = 404;
+            next({msg: 'User not found'});
         } else {
+            let u = user.toObject;
+            delete u.hashedPassword;
+            delete u.salt;
+            req.result = u;
             next();
         }
     });
+}, response('user'));
 
-}, (req, res, next) => {
-    var newUser = new User({
+userApp.post('/', (req, res, next) => {
+    let user = new User({
         email: req.body.email,
         password: req.body.password,
         name: req.body.name,
@@ -120,73 +123,53 @@ userApp.post('/', (req, res, next) => {
         course: req.body.course,
         segment: req.body.segment,
         role: req.body.role,
-        institution_name: req.body.institution_name,
+        institutionName: req.body.institutionName,
         state: req.body.state,
         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);
+    user.save((err) => {
+        if(err) {
+            log.error(err);
+            let errors = [];
+            for(let errName in err.errors) {
+                errors.push(err.errors[errName].message);
             }
-            res.status(400);
-            res.json({success: false, msg: errArray});
-        }
-         else {
-            res.status(201);
-            res.json({success: true, msg: 'Usuário cadastrado com sucesso!'});
+            console.log(errors);
+            res.statusCode = 400;
+            return res.json({err, errors});
         }
-    });
-});
-
-userApp.post('/authenticate', (req, res, next) => {
-    if (!req.body.email) {
-        res.status(400);
-        res.json({success: false, msg: 'O campo Email é obrigatório.'});
-    } 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
-                    var token = jwt.encode(user, secret);
+        // Create verification token
+        let verificationToken = new VerificationToken({
+            userId: user._id
+        });
 
-                    //returns user info including token as json
-                    res.json({success: true, token: 'JWT ' + token, msg: 'Usuário autenticado com sucesso'});
-                }
-                else {
-                    res.status(400);
-                    res.json({success: false, msg: ['A Senha informada é inválida.']});
+        verificationToken.createVerificationToken((err, token) => {
+            if(err) {
+                log.error(err);
+                return next(err);
+            }
+            let url = config.default.lde.url + '/verify';
+            let text = `Olá, ${user.name}, seja bem vindo ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${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);
+                    res.json({msg: 'User created'});
                 }
+                log.debug(`Message ${info.messageId} sent: ${info.response}`);
+                res.json({msg: 'User created'});
             });
-        }
+        });
     });
 });
 
diff --git a/src/libs/routes/verifyToken.js b/src/libs/routes/verifyToken.js
new file mode 100644
index 0000000000000000000000000000000000000000..425c3b6e05e2dae676e81c8c1a63c128ea7d8b3f
--- /dev/null
+++ b/src/libs/routes/verifyToken.js
@@ -0,0 +1,54 @@
+const express = require('express');
+
+const verifyTokenApp = express.Router();
+
+const libs = `${process.cwd()}/libs`;
+
+const log = require(`${libs}/log`)(module);
+
+const VerificationToken = require(`${libs}/models/verificationToken`);
+
+const User = require(`${libs}/models/user`);
+
+verifyTokenApp.get('/:token', (req, res, next) => {
+    let token = req.params.token;
+    console.log('verificando token');
+    VerificationToken.findOne({token: token}, (err, vToken) => {
+        if(err) {
+            log.error(err);
+            return next(err);
+        }
+        if(!vToken) {
+            // TODO: generate new verification token
+            console.log('Token não existe');
+            res.statusCode = 404;
+            return next({msg: 'Token not found', status:404});
+        }
+        User.findById(vToken.userId, (err, user) => {
+            if(err) {
+                log.error(err);
+                next(err);
+            }
+            user.verified = true;
+            user.save((err) => {
+                if(err) {
+                    log.error(err);
+                    next(err);
+                }
+            });
+            let u = user.toObject();
+            delete u.salt;
+            delete u.hashedPassword;
+            vToken.verified = true;
+            vToken.save((err) => {
+                if(err) {
+                    log.error(err);
+                    next(err);
+                }
+            });
+            res.json({msg: 'User verified', user: u});
+        });
+    });
+});
+
+module.exports = verifyTokenApp;
diff --git a/src/test/user.js b/src/test/user.js
index 9d6228284509f56682e7a7c6d781e79d6abb6d72..3109960bd98dfec2727c5ba7bf87b28148046ae7 100644
--- a/src/test/user.js
+++ b/src/test/user.js
@@ -29,598 +29,9 @@ const User = require('../libs/models/user');
 chai.use(chaiHttp);
 
 describe('Saves a user', () => {
-    beforeEach(() => {
-        User.remove({}, (err) => {
-            console.log('Test collection purged')
-        });
-    });
-
-    it('should save a user', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(201);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(true);
-            res.body.should.have.property('msg');
-            res.body.msg.should.be.equal('Usuário cadastrado com sucesso!');
-            done();
-        });
-    });
-
-    it('should not save a user without email', (done) => {
-        let newUser = {};
-        newUser.email = null;
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Email é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without password', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Senha é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user with invalid email', (done) => {
-        let newUser = {};
-        newUser.email = 'invalid email';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg.should.be.equal('O email informado é inválido.');
-            done();
-        });
-    });
-
-    it('should not save a user without a name', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Nome é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without CPF', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo CPF é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without schooling', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Escolaridade é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without segment', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Segmento é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without role', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Função é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without institution_name', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Instituição em que trabalha é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without state', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.city = 'Curitiba';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Estado é obrigatório.');
-            done();
-        });
-    });
-
-    it('should not save a user without city', (done) => {
-        let newUser = {};
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'Paraná';
-
-        chai.request(server)
-        .post('/api/v1/user/')
-        .set('content-type', 'application/x-www-form-urlencoded')
-        .set('x-apicache-bypass', 'true')
-        .send(newUser)
-        .end((err, res) => {
-            res.should.have.status(400);
-            res.should.be.json;
-            res.body.should.have.property('success');
-            res.body.success.should.equal(false);
-            res.body.should.have.property('msg');
-            res.body.msg[0].should.be.equal('O campo Cidade é obrigatório.');
-            done();
-        });
-    });
-
-})
-
-describe('Authenticates a user', () => {
-
-    beforeEach(() => {
-        User.remove({}, (err) => {
-            console.log('Test collection purged');
-        });
-    });
-
-    it('should authenticate a user', (done) => {
-        let newUser = new User();
-
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        newUser.save((err) => {
-            if (err) {
-                console.log('MongoDB error:' + err);
-            }
-        }).then(function(newuser){
-            chai.request(server)
-            .post('/api/v1/user/authenticate')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({email: 'lorem@ipsum.com',
-            password: '123mudar'})
-            .end((err, res) => {
-                let token;
-
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(true);
-                res.body.should.have.property('token');
-                token = res.body.token;
-                token.substr(0, 3).should.equal('JWT');
-                done();
-            });
-        });
-    });
-
-    it('should not authenticate a user with wrong password', (done) => {
-        let newUser = new User();
-
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        newUser.save((err) => {
-            if (err) {
-                console.log('MongoDB error:' + err);
-            }
-        }).then(function(newuser){
-            chai.request(server)
-            .post('/api/v1/user/authenticate')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({email: 'lorem@ipsum.com',
-            password: 'umasenhaerrada'})
-            .end((err, res) => {
-                res.should.have.status(400);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                res.body.should.have.property('msg');
-                res.body.msg[0].should.equal('A Senha informada é inválida.')
-                done();
-            });
-        });
-    });
-
-    it('should not authenticate a user with wrong email', (done) => {
-        let newUser = new User();
-
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        newUser.save((err) => {
-            if (err) {
-                console.log('MongoDB error:' + err);
-            }
-        }).then(function(newuser){
-            chai.request(server)
-            .post('/api/v1/user/authenticate')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({email: 'dolor@ipsum.com',
-            password: '123mudar'})
-            .end((err, res) => {
-                res.should.have.status(400);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                res.body.should.have.property('msg');
-                res.body.msg[0].should.equal('O Email informado não está cadastrado.')
-                done();
-            });
-        });
-    });
-
-    it('should not authenticate a user with missing email', (done) => {
-        let newUser = new User();
-
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        newUser.save((err) => {
-            if (err) {
-                console.log('MongoDB error:' + err);
-            }
-        }).then(function(newuser){
-            chai.request(server)
-            .post('/api/v1/user/authenticate')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({password: '123mudar'})
-            .end((err, res) => {
-                res.should.have.status(400);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                res.body.should.have.property('msg');
-                res.body.msg.should.equal('O campo Email é obrigatório.')
-                done();
-            });
-        });
-    });
-
-    it('should not authenticate a user with missing password', (done) => {
-        let newUser = new User();
-
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        newUser.save((err) => {
-            if (err) {
-                console.log('MongoDB error:' + err);
-            }
-        }).then(function(newuser){
-            chai.request(server)
-            .post('/api/v1/user/authenticate')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({email:'lorem@ipsum.com'})
-            .end((err, res) => {
-                res.should.have.status(400);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                res.body.should.have.property('msg');
-                res.body.msg.should.equal('O campo Senha é obrigatório.')
-                done();
-            });
-        });
-    });
-
-    it('should not authenticate a user with wrong password', (done) => {
-        let newUser = new User();
-
-        newUser.email = 'lorem@ipsum.com';
-        newUser.password = '123mudar';
-        newUser.name = 'Gute';
-        newUser.cpf = '08236017907';
-        newUser.schooling = 'Doutorado';
-        newUser.course = 'Ciência da Computação';
-        newUser.segment = 'Comunidade acadêmica';
-        newUser.role = 'Pesquisador';
-        newUser.institution_name = 'UFPR';
-        newUser.state = 'PR';
-        newUser.city = 'Curitiba';
-
-        newUser.save((err) => {
-            if (err) {
-                console.log('MongoDB error:' + err);
-            }
-        }).then(function(newuser){
-            chai.request(server)
-            .post('/api/v1/user/authenticate')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({email:'lorem@ipsum.com', password: '123'})
-            .end((err, res) => {
-                res.should.have.status(400);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                res.body.should.have.property('msg');
-                res.body.msg[0].should.equal('A Senha informada é inválida.')
-                done();
-            });
-        });
-    });
+    // beforeEach(() => {
+    //     User.remove({}, (err) => {
+    //         console.log('Test collection purged')
+    //     });
+    // });
 });