Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
secretKey = 12345-67890-09876-54321

TokenSecret = 12345-67890-09876-54321

PORT = 3000
mongoUrl = mongodb://localhost:27017/quiz
35 changes: 35 additions & 0 deletions Utils/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const crypto = require("crypto");

const genRandomString = function (length) {
return crypto
.randomBytes(Math.ceil(length / 2))
.toString("hex") /** convert to hexadecimal format */
.slice(0, length); /** return required number of characters */
};

const hashPassword = async (password, salt) => {
let config = {
iterations: 1000,
};
return new Promise((resolve, reject) => {
crypto.pbkdf2(
password,
salt,
config.iterations,
32,
"sha512",
(err, derivedKey) =>
err ? reject(err) : resolve(derivedKey.toString("hex"))
);
});
};

const comparePassword = async (userPassword, userSalt, password) => {
return userPassword === (await hashPassword(password, userSalt));
};

module.exports = {
hashPassword,
genRandomString,
comparePassword,
};
23 changes: 12 additions & 11 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const createError = require("http-errors");
const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const morgan = require("morgan");
const winston = require("./winston");
const rateLimit = require("express-rate-limit");
Expand All @@ -12,20 +11,21 @@ const cors = require("cors");
const compression = require("compression");
const chalk = require("chalk");

const passport = require("passport");

const dotenv = require("dotenv");
dotenv.config();

const authenticate = require("./authenticate");

const indexRouter = require("./routes/index");
const usersRouter = require("./routes/users");
const quizRouter = require("./routes/quizRouter");
const config = require("./config");

const mongoose = require("mongoose");
const Quizes = require("./models/quizes");

const DB = config.mongoUrl;

mongoose.set("autoIndex", true);

const connectDB = async () => {
const con = await mongoose.connect(DB, {
const con = await mongoose.connect(process.env.mongoUrl, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
Expand Down Expand Up @@ -56,8 +56,6 @@ app.set("view engine", "jade");

app.use(morgan("combined", { stream: winston.stream }));

app.use(cookieParser("12345-67890"));

// Limit requests from the same API
const limiter = rateLimit({
max: 100,
Expand All @@ -77,6 +75,8 @@ app.use(cors());

app.options("*", cors());

app.use(passport.initialize());

app.use(compression());

app.disable("x-powered-by");
Expand Down Expand Up @@ -106,7 +106,8 @@ app.use(function (err, req, res, next) {
);
// render the error page
res.status(err.status || 500);
res.render("error");
res.json({ err, message: err.message });
//res.render("error");
});

module.exports = app;
116 changes: 77 additions & 39 deletions authenticate.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,80 @@
exports.verifyUser = (req, res, next) => {

console.log(req.signedCookies);

if(!req.signedCookies.user) {
var authHeader = req.headers.authorization;

if(!authHeader) {
var err = new Error('You are not authosrised');
res.setHeader('WWW-Authenticate', 'Basic');
err.status = 401;
return next(err);
}

var auth = new Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(":");
var username = auth[0];
var password = auth[1];

if (username === 'admin' && password === 'password') {
res.cookie('user', 'admin', {signed: true})
next();
}
else {
var err = new Error('password is incorrect');
res.setHeader('WWW-Authenticate', 'Basic');
err.status = 401;
return next(err);
}
}
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const JwtStrategy = require("passport-jwt").Strategy;
const ExtractJwt = require("passport-jwt").ExtractJwt;
const jwt = require("jsonwebtoken");

const User = require("./models/Users");

const { comparePassword } = require("./Utils/utils");

passport.use(
new LocalStrategy(function (username, password, done) {
User.findOne(
{ username: username },
"username isAdmin passwordHash passwordSalt",
async function (err, user) {
if (err) {
return done(err);
}

if (!user) {
return done(null, false, { message: "Incorrect Username." });
}
const verifyPassword = await comparePassword(
user.passwordHash,
user.passwordSalt,
password
);
if (!verifyPassword) {
return done(null, false, { message: "Incorrect password." });
}

return done(null, user);
}
);
})
);

passport.serializeUser(function (user, done) {
done(null, user.id);
});

passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});

exports.generateToken = function (user) {
return jwt.sign(user, process.env.TokenSecret, { expiresIn: 36000 });
};

let opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = process.env.TokenSecret;

else {
if(req.signedCookies.user === 'admin') {
next();
}
else {
var err = new Error('cookie is invalid');
passport.use(
new JwtStrategy(opts, (jwt_payload, done) => {
User.findOne({ _id: jwt_payload._id }, "username isAdmin", (err, user) => {
if (err) {
return done(err, false);
} else if (user) {
return done(null, user);
} else {
return done(null, false);
}
});
})
);

err.status = 401;
return next(err);
}
exports.verifyUser = passport.authenticate("jwt", { session: false });
exports.verifyAdmin = (req, res, next) => {
if (req.user && req.user.isAdmin) {
return next();
} else {
err = new Error("You are not Authorized to perform this operation");
err.status = 403;
return next(err);
}
}
};
2 changes: 1 addition & 1 deletion bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var server = http.createServer(app);
* Listen on provided port, on all network interfaces.
*/

server.listen(port);
server.listen(port,()=> console.log(`Server is running on port ${port}`));
server.on('error', onError);
server.on('listening', onListening);

Expand Down
4 changes: 0 additions & 4 deletions config.js

This file was deleted.

107 changes: 107 additions & 0 deletions logs/app.log

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions models/Users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const mongoose = require("mongoose");

const Schema = mongoose.Schema;

const UserSchema = new Schema(
{
username: {
type: String,
trim: true,
required: true,
max: 64,
min: 3,
},

passwordSalt: {
type: String,
required: true,
max:16
},

passwordHash: {
type: String,
required: true,
},

isAdmin: {
type: Boolean,
required: true,
default: false,
},
},
{
timestamps: true,
}
);

const User = mongoose.model("Users", UserSchema);

module.exports = User;
Loading