Issues (208)

server/privacy.js (1 issue)

1
var express = require('express');
2
var extend  = require('extend');
3
var request = require('request');
4
5
// ------------------------------------------
6
//  CONSTRUCTOR
7
// ------------------------------------------
8
9
var init = function(){
10
  info('Starting PrivacyManager ...');
11
  salt();
12
  
13
  return PrivacyManager;
14
}
15
16
// ------------------------------------------
17
//  USERS
18
// ------------------------------------------
19
20
var findByUsername = function (username, fn) {
21
  setTimeout(function(){ // slow bruteforce
22
    
23
    var user = Config.auth['local-users'][username]
24
    if (user){ return fn(null, user); }
25
    return fn(null, null);
26
    
27
  }, 1000);
28
}
29
30
// ------------------------------------------
31
//  PASSPORT
32
// ------------------------------------------
33
34
var passport = require('passport');
35
36
passport.serializeUser  (function(user, done) { /*info('serializeUser',   user);*/ done(null, user); });
37
passport.deserializeUser(function(obj, done)  { /*info('deserializeUser', obj);*/  done(null, obj);  });
38
39
// ------------------------------------------
40
//  LOCAL STRATEGY
41
// ------------------------------------------
42
43
var setLocalStrategy = function(passport, router){
44
  router.get('/login', function(req, res, next) {
45
    res.render('portal/login.ejs', { 'redirect' : req.query.redirect });
46
  });
47
  
48
  router.post('/login', 
49
    passport.authenticate('local', { failureRedirect: '/login', failureFlash: false }), function(req, res) { 
50
      if (req.body.redirect){
51
        res.redirect(req.body.redirect);
52
      } else {
53
        res.redirect('/');
54
      } 
55
    }
56
  );
57
  
58
  var LocalStrategy = require('passport-local').Strategy;
59
  passport.use(new LocalStrategy(local));
60
}
61
62
var local = function(username, password, done) {
63
  process.nextTick(function () {
64
    findByUsername(username, function(err, user) {
65
      
66
      if (err) { return done(err); }
67
      if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
68
      
69
      var passHash = hash(password);
70
      if (user.password != passHash) { 
71
        info('Invalid password');
72
        return done(null, false, { message: 'Invalid password' }); 
73
      }
74
      
75
      return done(null, user);
76
    });
77
  });
78
}
79
80
// ------------------------------------------
81
//  ROUTER
82
// ------------------------------------------
83
84
var Router = express.Router();
85
Router.use(passport.initialize());
86
Router.use(passport.session());
87
88
Router.get('/logout', function(req, res){
89
  req.logout();
90
  res.redirect('/');
91
});
92
93
// Set local strategy
94
setLocalStrategy(passport, Router);
95
96
// Set google strategy
97
// setGoogleStrategy(passport, Router);
98
99
// Security
100
Router.all('*', function(req, res, next) {
101
  
102
  // Security Hole: ByPass for client
103
  if ( req.path.startsWith('/sarah') 
104
    || req.path.startsWith('/askme')
105
    || req.path.startsWith('/standby')){
106
    return next();
107
  }
108
  
109
  // Set user authentication 
110
  if (Config.auth && Config.auth['local-users']){
111
  if (!req.isAuthenticated()){ 
112
    
113
    var redirectURL = encodeURIComponent(req.url);
114
    return res.redirect('/login?redirect='+redirectURL); }  
115
  } else { req.user = { displayName : '' }}
116
  
117
  next();
118
});
119
120
Router.get('/profile', function(req, res){
121
  res.render('portal/profile.ejs', { "user" : req.user });
122
});
123
124
Router.post('/profile', function(req, res){
125
  
126
  var username    = req.body.username;
127
  var password    = req.body.password;
128
  var newPassword = req.body.newpassword;
129
  var displayName = req.body.displayname;
130
  
131
  // Retrieve user
132
  var user = Config.auth['local-users'][req.user.login];
133
  
134
  // Check Old password
135
  var oldHash = hash(password);
136
  if (user.password !== oldHash){
137
    res.redirect('/');
138
    return;
139
  }
140
  
141
  // Update new password
142
  var newHash = hash(newPassword);
143
  user.password = newHash;
144
  user.displayName = displayName;
145
  SARAH.ConfigManager.save();
146
  
147
  res.redirect('/');
148
});
149
150
Router.get('/profile/delete', function(req, res){
151
  delete Config.auth['local-users'][req.query.id]
152
  SARAH.ConfigManager.save();
153
});
154
155
Router.all('/profile/create', function(req, res){
156
  var msg = undefined;
157
  var op  = req.body.op;
158
  
159
  if (op){
160
    if (req.body.login && req.body.password && req.body.displayname){
161
      Config.auth['local-users'][req.body.login] = {
162
        login       : req.body.login,
163
        password    : hash(req.body.password),
164
        displayName : req.body.displayname,
165
      }
166
      SARAH.ConfigManager.save();
167
    } else { msg = i18n('portal.error.missing'); }
168
  }
169
  
170
  res.render('portal/modal-profile.ejs', { 'message': msg, 'op': op });
171
});
172
173
// ------------------------------------------
174
//  CRYPTO
175
// ------------------------------------------
176
177
var bcrypt = require('bcryptjs');
178
179
var ITERATION = 10000;
180
var hash   = function(password){
181
  var salt = Config.auth['local-salt'];
182
  //    salt = new Buffer(salt, 'hex');
183
  //var key  = Crypto.pbkdf2Sync(password, salt, ITERATION, 64);
184
  //var hash = 'pbkdf2$' + ITERATION + '$' + key.toString('hex') + '$' + salt.toString('hex');
185
  var hash = bcrypt.hashSync(password, salt);
186
  return hash;
187
}
188
189
var salt = function(){
190
  if (Config.auth['local-salt'] != false) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
191
  
192
  // var salt = ('salt' + (Math.random()*10000)).replace('.','0');
193
  var salt = bcrypt.genSaltSync(10);
194
  var sarahId = 'uid-' + (new Date()).getTime();
195
  registerSARAH(sarahId);
196
  
197
  Config.auth['local-uid']  = sarahId
198
  Config.auth['local-salt'] = salt
199
  Config.auth['local-users']          = Config.auth['local-users']          || {};
200
  Config.auth['local-users']['admin'] = Config.auth['local-users']['admin'] || {};
201
  
202
  var admin = Config.auth['local-users']['admin'];
203
  admin.login       = 'admin';
204
  admin.password    = hash('password');
205
  admin.displayName = 'Admin';
206
  SARAH.ConfigManager.save();
207
}
208
209
var AMZID = '5eVBwYTHp21nzkXrcCC6e4UM93Pr2QMX5cLeD50S';
210
var registerSARAH = function(id){
211
 var url = 'http://tracker.sarah.encausse.net';
212
  request({ 
213
    'uri' : url+'?trackerId='+id, 
214
    'json' : true, 
215
    'headers': {'x-api-key': AMZID } 
216
  },
217
  function (err, response, json){
218
    if (err || response.statusCode != 200) { 
219
      return warn("Can't register SARAH into the Cloud", err, response);   
220
    }
221
  });
222
}
223
224
225
// ------------------------------------------
226
//  PUBLIC
227
// ------------------------------------------
228
229
var PrivacyManager = {
230
  'init' : init,
231
  'Router' : Router
232
}
233
234
// Exports Manager
235
exports.init = PrivacyManager.init;