-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
396 lines (323 loc) · 14.4 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
require('dotenv').config(); //Håller hemligheter hemliga .env
const express = require('express');
const bodyParser = require('body-parser');
const ejs = require('ejs');
const mongoose = require('mongoose');
//!!const encrypt = require('mongoose-encryption'); -Raderar dessa för att istället använda HASHING
//!!const md5 = require('md5'); UTRADERAD//HASHING Password - Impossible to reverse
//!!const bcrypt = require('bcrypt'); UTRADERAD BCRYPT
//!!const saltRounds = 10; UTRADERAD BCRYPT SALTING
const session = require('express-session'); //Cookies and Sessions
const passport = require('passport'); //Cookies and Sessions
const passportLocalMongoose = require('passport-local-mongoose'); //Cookies and Sessions
const GoogleStrategy = require('passport-google-oauth20').Strategy;//Using the const as a strategy
const findOrCreate = require('mongoose-findorcreate');
const rateLimit = require('express-rate-limit');
const MongoClient = require('mongodb').MongoClient;
const auditLog = require('audit-log'); // DECLARE AUDITLOG
const app = express();
//----SSL-----------------------
const https = require('https');
const http = require('http');//testmiljö
const fs = require("fs");
//---------------------------------
//AUDIT LOGGING -----------------------
//audit loggar i mongoDB, loggar user aktivitet
auditLog.addTransport("mongoose", {connectionString: "mongodb://localhost/auditdb"})
//---------------------------------------
const PORT = process.env.PORT || 3000
const uri = process.env.MONGODB;
//SSL -private key and certifiering & Asymmetric encryption---------- OPENSSL ÄR TESTMILJÖ
//Certificate , hemliga nycklar till SSL/TSL, som tillåter hemlig kommunikation mellan server och browser
const options = {
key: fs.readFileSync('nattas-key.pem'),
cert: fs.readFileSync('nattas-cert.pem')
}; //----------------------------------
//Övervakar app mot attacker /Monitoring
app.use('/healthcheck', require('./routes/healthcheck.routes'));
app.use(express.static('public')); //use the location for our css
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({
extended: true
}));
//session cookies /Auktorisering
app.use(session({
secret:"Our little secret.",
resave: false,
saveUninitialized: false,
//cookie: { secure: true }
}));
app.use(passport.initialize()); //starting passport encryption - passport startar kryptering
app.use(passport.session()); //passport starting session cookies - passport startar session cookies
//connection to our Mongo DB where we have a document for our users.
//if user registers with Google we can only see the Google ID and submitted Secret
//if user registers via the form, we can see username, encrypted password and secret
mongoose.connect('mongodb://localhost:27017/userDB', {useNewUrlParser: true}); //Skapar connection till MongoDB med namnet userDB -Se i Compass
//mongoose.set("useCreateIndex", true); //this is no longer needed in Mongoose 6
//Logging
const userSchema = new mongoose.Schema ({
email: String,
password: String,
googleId: String, //id som hittar user som loggar in genom google, och inte skapar ny id varje gång i DB
secret: String
}); //Skapar en ny userSchema i mongoDB och Sparar email & password i mongoDB
//krypterar när man (call save plugin) , saltar och hashar automatiskt åt oss
userSchema.plugin(passportLocalMongoose); // call plugin save = crypting
//dekrypterar (när man call find plugin) , hittar avändare genom google id eller skapar om user inte finns
userSchema.plugin(findOrCreate); // call plugin find = decrypting
//UTKOMMENTERAT FÖR ATT ISTÄLLET ANVÄNDA HASHING SOM ÄR SÄKRARE KRYPTERING
//userSchema.plugin(encrypt, { secret: process.env.SECRET, encryptedFields: ["password"] });
//Kommer att kryptera(encrypt) hela databasen
//Lägger till encryptedFields for att kategorisera ut och endast kryptera "password" -i detta fall.
const User = new mongoose.model('User', userSchema); //Skapar User för userSchema i mongoDB
// PASSPORT------------------------------------
//Autentisering
passport.use(User.createStrategy());
//serialize skapar krypterad cookie med personens id, funkar för alla strategies
// skapar cookies with user ID
passport.serializeUser(function(user, done){
done(null, user.id)
});
//deserialize tar sönder cookie så vi kan identifiera personen
// "opens" the cookie to identify user by ID
passport.deserializeUser(function (id, done) {
User.findById(id, function(err, user){
done(err, user);
});
});
//passport google oauth, autentiserar user med new google strategy
passport.use(new GoogleStrategy({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/secrets", //URL från Google Developers
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo" //Instead of retrieving the info from the users google+-account, instead we're retrieving from the user-info
}, //hämtar info från userinfo inte google+ account -futureproofed
//Auktorisering , google skickar accesstoken så att vi kan använda data så länge det behövs
function(accessToken, refreshToken, profile, cb) {
console.log(profile)
//installera paket mongoose findOrCreate, skapar el hittar id och profil genom googleid
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
/* ----------------------------------------
### ALL ROUTES ###
*/
//Lägger till en register-spärr där man endast kan logga in 10ggr/15min
const createLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // Limit each IP to 10 requests per `window` (we have set a window to be = 15 minutes)
message: "Too many accounts created from this IP, please try again after 15 minutes",
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
}) //Lägger till en request-spärr där man endast kan requesta sidan 10ggr/15min
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // Limit each IP to 10 requests per `window` (we have set a window to be = 15 minutes)
message: "Too many requests sent from this IP, please try again after 15 minutes",
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
})
//**HOME ROUTE
app.get("/", function(req, res){
res.render("home") //Skickar användare till home som standard, utgår ifrån Home
});
//**PASSPORT AND GOOGLE ROUTE-------------------
//opens up window for using google-sign in
//passport auth med google strategy, popup ruta för att user ska logga in
app.get("/auth/google", //getting info from google-server | Asking google server for the users profile
passport.authenticate('google', { scope: ["profile"] })
); //Denna route skickar användaren vidare till google-inloggning
//google skickar tbx user, autentiserar user lokalt och blir hänvisad till appen för login
app.get("/auth/google/secrets",
passport.authenticate('google', { failureRedirect: "/login" }),
function(req, res) {
// Successful authentication, redirect to secrets-page.
res.redirect("/secrets");
});
//**LOGIN ROUTE ----------------------
app.get("/login", limiter, function(req, res){
res.render("login") //Skickar användaren till Login
});
//**TERMS ROUTE ----------------------
app.get("/terms", function(req, res){
res.render("terms") //Skickar användaren till Terms
});
//REGISTRATION ROUTES ----------------------
app.get("/register", limiter, function(req, res){
res.render("register") //Skickar användaren till Register
});
//**SECRETS ROUTES ----------------------------
//-----UTRADERAD VERSION AV app.get Secrets
// app.get("/secrets", function (req, res){
// if (req.isAuthenticated()){
// res.render("secrets");
// } else {
// res.redirect("/login");
// }
// });
//----ANOTHER SECRET ROUTE-------------------------
//hittar alla secrets som blir inskickade
app.get("/secrets", function (req, res){
//renders all submitted secrets
User.find({"secret": {$ne: null}}, function(err, foundUsers){
if(err){
console.log(err)
} else {
if(foundUsers) {
res.render("secrets", {usersWithSecrets: foundUsers});
}
}
});
});
//---------------------------------------------------
//**SUBMIT SECRET ROUTE-------------------------------
//if a user wants to access the /submit-page they need to be logged in
//- if not, they will be redirected to Log In
//skicka in en secret, om dom inte är inloggade skickas dom till login först
app.get("/submit", function (req,res) {
if(req.isAuthenticated()){
res.render("submit")
}else {
res.redirect("/login");
}
});
//secret blir inskickad
//när user blir aut, sparas info i req.user
//om samma user loggar in igen så lagras deras secret på deras id
app.post("/submit", function(req, res) {
const submittedSecret = req.body.secret;
console.log(req.user.id);
// Once the user is authenticated and their session gets saved,
// their user details are saved to req.user.
// console.log(req.user.id);
User.findById(req.user.id, function(err, foundUser){
if (err) {
console.log(err)
} else {
if(foundUser) {
foundUser.secret = submittedSecret;
foundUser.save(function(){
res.redirect("/secrets");
});
}
auditLog.logEvent(foundUser.username, 'A SECRET CHARED',
"SUBMITTED SECRET", foundUser.secret, 'SECRET', 'User successfully submitted a Secret<3');
}
});
});
//-----------------------------------------------------
//**LOGOUT ROUTE------------------------------------------
//loggar ut användare avslutar session/cookies
app.get("/logout", function(req, res, next) {
// remove the req.user property and clear the login session
req.logout();
// don't destroy session data when logout is used
//req.session = null;
// redirect to homepage
res.redirect('/');
});
/*
The user gets redirected to the Secrets-section if registration or log in = success.
If not, they remain on the same page
*/
//**REGISTER ROUTE NEW USER */
//om login lyckas kommer user in till secrets , annars blir user kvar på register
//registrerar nya anändare med passport med local strategy
app.post("/register", function(req, res){
User.register({username: req.body.username}, req.body.password, function(err, user){
if(err){
console.log(err);
res.redirect("/register");
} else {
passport.authenticate("local")(req, res, function(){
res.redirect("/login");
});
}
});
});
//------OLD REGISTER ROUTE FOR BCRYPT PASSWORD AND SALTING------
// app.post('/register', function(req, res){
// bcrypt.hash(req.body.password, saltRounds, function(err, hash) {
// //Store hash in your password DB
// const newUser = new User({
// email: req.body.username, //Hämtar Username ifrån register-sidan
// password: hash
// //UTRADERAD MD5 --password: md5(req.body.password) //Hämtar Password ifrån register-sidan -md5 = hashing
// });
// newUser.save(function(err){
// if (err) {
// console.log(err);
// } else {
// res.render('secrets') //Skickar användaren till sidan Secrets(Loggar in)
// }
// });
// });
// });
//----------------------------------------------------------------
//LOGIN ROUTES ----------------------
//kollar så att username och password matchar med passport
app.post("/login", function(req, res){
const user = new User({
username: req.body.username,
password: req.body.password
});
//auditlog funkade bara i denna function eftersom det är en post
auditLog.logEvent(user.username, 'ACCESS',
"LOGIN ATTEMPT", 'ATTEMPTED LOGIN', 'USER-LOGIN', 'A USER TRIED LOGIN');
//This req comes from passport
req.login(user, function(err){
if(err){
console.log(err);
res.redirect("/login");
} else{
passport.authenticate("local")(req, res, function(){
res.redirect("/secrets");
});
}
});
});
//-----OLD LOGIN ROUTE FOR BCRYPT & SALTING-----------
// app.post('/login', function(req, res){
// const username = req.body.username;
// const password = req.body.password
// //UTRADERAT MD5 ----const password = md5(req.body.password); //Lägger md5 här också för att kunna matcha den hashade lösenordet.
// //Letar i userDB efter inmatad liknelse, om den hittar en identisk sparad ObjectID så kommer den att matcha och logga in
// User.findOne({email: username}, function(err, foundUser){
// if (err) {
// // Error ifall Username och Password inte matchar som i userDB/Compass
// console.log(err);
// } else {
// if (foundUser) {
// bcrypt.compare(password, foundUser.password, function(err, result) {
// // res == true
// if (result === true) {
// res.render('secrets');
// //Ifall username och password är korrekt så skickas användaren vidare till Secrets-sidan, vilket innebär att användaren blivit autentiserade
// }
// });
// //Ifall password matchar med username i userDB så kommer den att logga in, i annat fall blir det error
// //UTRADERAT MD5 ---if (foundUser.password === password) {
// }
// }
// });
// });
//-------------------------------------------------------
//Accesslogging/Turing Test, recaptcha ser till att du inte är en robot
//räknar även antal försök till login
function recaptcha_callback() {
var loginBtn = document.querySelector('#login-btn');
loginBtn.removeAttribute('disabled');
loginBtn.style.cursor = 'pointer';
}
// app.listen(3000, function() {
// console.log("Server running on port 3000 BIATCH");
// });
//SSL
http.createServer(app).listen(PORT, function(){
console.log('info', `STARTED LISTENING ON PORT ${PORT} BIATCH!`);
});
https.createServer(options, app).listen(443, function(){
console.log('HTTPS listening on 443');
});