diff --git a/app.js b/app.js
index 5e2f1d76..71b52bf8 100644
--- a/app.js
+++ b/app.js
@@ -12,6 +12,8 @@ var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var MongoStore = require('connect-mongo')(session);
+var csurf = require('csurf')
+
var app = express();
app.locals.pretty = true;
@@ -46,6 +48,21 @@ app.use(session({
})
);
+app.use(csurf({ }));
+
+app.use(function(request,response,next){
+ app.locals._token = request.csrfToken()
+ next()
+})
+
+app.use(function (err, req, res, next) {
+ if (err.code !== 'EBADCSRFTOKEN') return next(err)
+
+ // handle CSRF token errors here
+ res.status(403)
+ res.send('Form tampered with')
+})
+
require('./app/server/routes')(app);
http.createServer(app).listen(app.get('port'), function(){
diff --git a/app/public/js/controllers/homeController.js b/app/public/js/controllers/homeController.js
index 90255a8d..5b07b2ac 100644
--- a/app/public/js/controllers/homeController.js
+++ b/app/public/js/controllers/homeController.js
@@ -10,6 +10,9 @@ function HomeController()
// confirm account deletion //
$('#account-form-btn1').click(function(){$('.modal-confirm').modal('show')});
+// get csrf_token
+ var token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
+
// handle account deletion //
$('.modal-confirm .submit').click(function(){ that.deleteAccount(); });
@@ -20,6 +23,9 @@ function HomeController()
$.ajax({
url: '/delete',
type: 'POST',
+ headers: {
+ 'CSRF-Token': token
+ },
success: function(data){
that.showLockedAlert('Your account has been deleted.
Redirecting you back to the homepage.');
},
@@ -35,6 +41,9 @@ function HomeController()
$.ajax({
url: '/logout',
type: 'POST',
+ headers: {
+ 'CSRF-Token': token
+ },
data: {logout : true},
success: function(data){
that.showLockedAlert('You are now logged out.
Redirecting you back to the homepage.');
diff --git a/app/server/modules/account-manager.js b/app/server/modules/account-manager.js
index 195d52c0..05a44aba 100644
--- a/app/server/modules/account-manager.js
+++ b/app/server/modules/account-manager.js
@@ -114,6 +114,17 @@ exports.addNewAccount = function(newData, callback)
});
}
+function validateEmail(email, _id) {
+ return new Promise(function(resolve, reject) {
+ return accounts.find({email: email}).toArray(function(err, records) {
+ if (err) reject(err);
+ if (records.length > 1) reject('xerox')
+ if (records.length === 1 && records[0]._id.toString() !== _id) reject('imposter')
+ resolve(true);
+ });
+ });
+}
+
exports.updateAccount = function(newData, callback)
{
let findOneAndUpdate = function(data){
@@ -123,7 +134,14 @@ exports.updateAccount = function(newData, callback)
country : data.country
}
if (data.pass) o.pass = data.pass;
- accounts.findOneAndUpdate({_id:getObjectId(data.id)}, {$set:o}, {returnOriginal : false}, callback);
+
+ validateEmail(data.email, data.id)
+ .then(function() {
+ accounts.findOneAndUpdate({_id:getObjectId(data.id)}, {$set:o}, {returnOriginal : false}, callback);
+ })
+ .catch(function() {
+ callback('email-taken');
+ });
}
if (newData.pass == ''){
findOneAndUpdate(newData);
diff --git a/app/server/routes.js b/app/server/routes.js
index 8601d5d8..5724a4b4 100644
--- a/app/server/routes.js
+++ b/app/server/routes.js
@@ -79,6 +79,9 @@ module.exports = function(app) {
country : req.body['country']
}, function(e, o){
if (e){
+ if (e === 'email-taken') {
+ return res.status(400).send('email-taken');
+ }
res.status(400).send('error-updating-account');
} else{
req.session.user = o.value;
diff --git a/app/server/views/account.pug b/app/server/views/account.pug
index e15553fc..7f5c1aeb 100644
--- a/app/server/views/account.pug
+++ b/app/server/views/account.pug
@@ -36,6 +36,8 @@ input(type='hidden', value= user._id)#userId
.col-sm-9
input.form-control#pass-tf(type='password', name='pass', value='')
+ input(type="hidden" name="_csrf" value= _token)
+
hr
.form-buttons
button(type='button')#account-form-btn1.btn.btn-outline-dark
diff --git a/app/server/views/layout.pug b/app/server/views/layout.pug
index 310c2355..ad1cb71b 100644
--- a/app/server/views/layout.pug
+++ b/app/server/views/layout.pug
@@ -6,10 +6,11 @@ html
link(rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous")
link(rel='stylesheet', href='/css/style.css')
link(rel='stylesheet', href='//cdnjs.cloudflare.com/ajax/libs/github-fork-ribbon-css/0.1.1/gh-fork-ribbon.min.css')
+ meta(name="csrf-token" content=_token)
body
block content
script(src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous")
script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous")
script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous")
script(src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.2/jquery.form.min.js")
- block scripts
\ No newline at end of file
+ block scripts
diff --git a/app/server/views/login.pug b/app/server/views/login.pug
index 832ae5e6..cbda9740 100644
--- a/app/server/views/login.pug
+++ b/app/server/views/login.pug
@@ -19,6 +19,9 @@ block content
button(type='submit')#btn_sign_in.btn.btn-primary
span.fa.fa-lock
| Sign In
+
+ input(type="hidden" name="_csrf" value= _token)
+
hr
.btm-links
#forgot-password
@@ -33,4 +36,4 @@ block scripts
script(src='/js/views/login.js')
script(src='/js/controllers/loginController.js')
script(src='/js/form-validators/loginValidator.js')
- script(src='/js/form-validators/emailValidator.js')
\ No newline at end of file
+ script(src='/js/form-validators/emailValidator.js')
diff --git a/app/server/views/modals/lost-password.pug b/app/server/views/modals/lost-password.pug
index a9e5e023..89bb1aa7 100644
--- a/app/server/views/modals/lost-password.pug
+++ b/app/server/views/modals/lost-password.pug
@@ -12,6 +12,7 @@
label Please enter the email address associated with your account
input.form-control(type="email", id='email-tf', name="email").required
.alert.alert-danger.hide
+ input(type="hidden" name="_csrf" value= _token)
.modal-footer
button(data-dismiss="modal")#cancel.btn.btn-outline-dark Cancel
button(type="submit")#retrieve-password-submit.btn.btn-primary Submit
diff --git a/app/server/views/modals/reset-password.pug b/app/server/views/modals/reset-password.pug
index 2ae5944c..7ec5750c 100644
--- a/app/server/views/modals/reset-password.pug
+++ b/app/server/views/modals/reset-password.pug
@@ -12,5 +12,6 @@
label Please enter your new password
input.form-control(type="password", name="pass", id='pass-tf').required
.alert.alert-danger.hide
+ input(type="hidden" name="_csrf" value= _token)
.modal-footer
button(type="submit" form="set-password-form")#set-password-submit.btn.btn-primary Submit
diff --git a/package.json b/package.json
index 2b61b737..72cbaf22 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"body-parser": "^1.19.0",
"connect-mongo": "^3.2.0",
"cookie-parser": "^1.4.5",
+ "csurf": "^1.11.0",
"emailjs": "^2.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",