mongoose encrypt

  • the way that mongoose encrypt works is that it will encrypt when you call save and decrypt when you call find.
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
const mongoose = require("mongoose");
const encrypt = require("mongoose-encryption");


const userSchema= new mongoose.Schema({
email: String,
password: String
});
// no longer a simple Javascript object but it's actually an object that's created from the mongoose schema class

const secret ="Thisisoutlittlesecret."
userSchema.Schema.plugin(encrypt,{secret: secret, encryptedFields:["password"]});

const User = new mongoose.model("User", userSchema);

app.post("/register", function(req,res){
const newUser = new User({
email: req.body.username,
password: req.body.password
});
newUser.save().then(() => {
res.render("secrets");
})
.catch((err) => {
console.log(err);
});
});

app.post("/login", function(req,res){
const username = req.body.username;
const password = req.body.password;

User.findOne({email: username}).then((foundUser)=>{
if(foundUser){
if(foundUser.password === password){
res.render("secrets");
}
}
})
.catch((err) => {
console.log(err);
});
});


environment variable (store sensetive inf)

dotenv package

  • make a .env file in root directory

  • add -> require(‘dotenv’).config(); // put this on top in app.js

  • in .env, the format is like:

    1
    NAME = VALUE   

    NOTICE: no space in between and no quotation marks, NO SEMI COLON !!!!!!!

.env:

1
SECRET=Thisisoutlittlesecret.

app.js:

1
2
3
4
require('dotenv').config(); // put this on top


const secret = process.env.SECRET;

hashing

hash function: very fast to encode but almost impossible to go backwards

md5 Hashes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const md5 = require("md5");



app.post("/register", function(req,res){
const newUser = new User({
email: req.body.username,
password: md5(req.body.password)
});
newUser.save().then(() => {
res.render("secrets");
})
.catch((err) => {
console.log(err);
});
});

hashing & salting

The reason why is a hashing algorithm does not inherently produce a unique string for the same password text each time it’s received. In other words, suppose your password looks like the example above (Password@1234). Each time the algorithm receives the same input string, it will always produce the same hash string (i.e. 0F1BA603C1A843A3D02D6C5038D8E959). This is not ideal because a hacker can launch a rainbow attack on your database to crack the passwords stored inside.

Our problem with hashing is fixed with a simple solution: using salt. Salt is a randomly generated, fixed-length value that is designed to be unique with each user password. Salt is appended with the current password string and fed into the hashing system to produce a newly hashed result every time a user creates a password. This means that if you and I have the same password, our hashed strings would be different. And since rainbow table attacks heavily depend on finding a match, it would render them useless.

The bcrypt library, which creates both salt and hashed data with strong cryptography algorithms backing it, is great for this purpose.

salt round

When we talk about “hashing salt rounds,” we refer to the process of repeatedly applying the hashing and salting operations a specific number of times. Each iteration is known as a round. The purpose of using multiple rounds is to slow down the hashing process, making it more time-consuming and resource-intensive for an attacker attempting to crack the hashed passwords.

bcrypt Hashes

  • You can use nvm to upgrade or downgrade your node version.

    go to nvm github, install the script with the command in github

    go to terminal type -> nvm install 10.15.0

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
npm i bcrypt


const bcrypt = require("bcrypt");
app.post("/register", function(req,res){
const saltRounds = 10;
bcrypt.hash(req.body.password , saltRounds, function(err, hash){
const newUser = new User({
email: req.body.username,
password: hash
});
newUser.save().then(() => {
res.render("secrets");
})
.catch((err) => {
console.log(err);
});
});

});

app.post("/login", function(req,res){
const username = req.body.username;
const password = req.body.password;

User.findOne({email: username}).then((foundUser)=>{
if(foundUser){
// if(foundUser.password === password){
// res.render("secrets");
// }
bcrypt.compare(password, foundUser.password, function(err, result){
if(result === true){
res.render("secrets");
}

});
}
})
.catch((err) => {
console.log(err);
});
});




watch Angela37节. 359 for how cookie works.

passport

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
//jshint esversion:6
require('dotenv').config(); // put this on top
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
const mongoose = require("mongoose");
const encrypt = require("mongoose-encryption");
const app = express();

// 1. REQUIRE MODULES
const session = require("express-session");
const passport = require("passport");
const passportLocalMongoose = require("passport-local-mongoose");
//dont need to require passport-local, cause passport-local-mongoose will need passport-local. but our code wont urefer to passport-local

app.use(express.static("public"));
app.set("view engine", "ejs");
app.use(bodyParser.urlencoded({extended:true}));
// 2. tell app to use session package and set up initialization
app.use(session({
secret:"Our little secret.",
resave: false,
saveUnitialized: false

}));
//3. initialize passport
app.use(passport.initialize());
//4.use passport to manage our session
app.use(passport.session());


mongoose.connect("mongodb+srv://dxexperiments-user:DrEuMg7KfFImh774@dxvignettes.vtnenqy.mongodb.net/test");

const userSchema= new mongoose.Schema({
email: String,
password: String
});
//5. setup userSchema to use passport local mongoose as a plugin
userSchema.plugin(passportLocalMongoose); //


const User = new mongoose.model("User", userSchema);

//6. use passport local mongoose to create a local log in strategy and set up passport serialize and deserialize
passport.use(User.createStrategy());

// use static serialize and deserialize of model for passport session support
passport.serializeUser(User.serializeUser()); //serialize
passport.deserializeUser(User.deserializeUser()); //deserialize


app.get("/", function(req,res){
res.render("home");
});
app.get("/login", function(req,res){
res.render("login");
});
app.get("/register", function(req,res){
res.render("register");
});
app.get("/secrets", function(req,res){
if(req.isAuthenticated()){
res.render("secrets");
}else{
res.redirect("/login");
}

});

app.get("/logout",function(req,res){
req.logout(function(err) {
if (err) {
console.log(err);
}
res.redirect('/');
});

});


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(){ //authenticate the user
res.redirect("/secrets");
})
}
});

});

app.post("/login", function(req,res){

const user = new User({
username: req.body.username,
password: req.body.password
});

req.login(user, function(err){
if(err){
console.log(err);
}else{
passport.authenticate("local")(req,res,function(){ //authenticate the user
res.redirect("/secrets");
});
}
})

});


app.listen("3000",function(){
console.log("listening on port 3000");
});

OAuth

useful websites:

check if you has been pwned: https://haveibeenpwned.com/

password-checker: http://password-checker.online-domain-tools.com/

https://plaintextoffenders.com/