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; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
![]() |
|||
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; |
||
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; |