Implement auth with jwt and add endpoints

This commit is contained in:
rui hildt 2020-05-08 13:12:10 +02:00
parent fce5a162d3
commit 4b5a5b2477
8 changed files with 218 additions and 3 deletions

View File

@ -6,6 +6,7 @@ module.exports = {
updateAccount,
deleteAccount,
getMeetingsByAccountId,
getAccountByEmail,
};
function addAccount(data) {
@ -67,3 +68,18 @@ function getAccountById(id) {
'latest_time',
);
}
function getAccountByEmail(email) {
return db('account')
.where({ email })
.first()
.select(
'id',
'username',
'password',
'email',
'timezone',
'earliest_time',
'latest_time',
);
}

View File

@ -3,10 +3,11 @@ const router = express.Router();
const bcrypt = require('bcryptjs');
const Account = require('../models/accountModel');
const { saltingRounds } = require('../../config/config');
router.post('/', async (req, res) => {
const data = { ...req.body };
const hash = bcrypt.hashSync(data.password, 14);
const hash = bcrypt.hashSync(data.password, saltingRounds);
data.password = hash;
try {
@ -22,7 +23,7 @@ router.put('/:id', async (req, res) => {
const id = req.params.id;
if (data.password) {
const hash = bcrypt.hashSync(data.password, 14);
const hash = bcrypt.hashSync(data.password, 10);
data.password = hash;
}
@ -78,4 +79,18 @@ router.get('/:id', async (req, res) => {
}
});
router.get('/:email', async (req, res) => {
const email = req.params.email;
try {
const account = await Account.getAccountByEmail(email);
res.status(200).json(account);
} catch (error) {
res.status(500).json({
message: `Account with ${email} doesn't exist.`,
error,
});
}
});
module.exports = router;

48
api/routes/authRoute.js Normal file
View File

@ -0,0 +1,48 @@
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const Account = require('../models/accountModel');
const { saltingRounds } = require('../../config/config');
const { generateToken } = require('../../helpers/authJwt');
router.post('/register', async (req, res) => {
const data = req.body;
data.password = bcrypt.hashSync(data.password, saltingRounds);
try {
const [user] = await Account.addAccount(data);
const token = generateToken(user);
res.status(201).json({ user, token });
} catch (error) {
res.status(500).json({
message: `Failed to add new account.`,
error,
});
}
});
router.post('/login', async (req, res) => {
let { email, password } = req.body;
try {
const user = await Account.getAccountByEmail(email);
if (bcrypt.compareSync(password, user.password)) {
const token = generateToken(user);
res.status(200).json({
message: `Welcome ${user.username}!`,
token,
});
} else {
throw new Error();
}
} catch (error) {
res.status(401).json({
message: `Invalid Credentials`,
});
}
});
module.exports = router;

View File

@ -9,6 +9,7 @@ const meetingsRoute = require('./routes/meetingRoute');
const participantsRoute = require('./routes/participantRoute');
const possibleDatesRoute = require('./routes/possibleDateRoute');
const availibilityRoute = require('./routes/availibilityRoute');
const authRoute = require('./routes/authRoute');
const server = express();
@ -28,6 +29,7 @@ server.use('/api/meetings', meetingsRoute);
server.use('/api/participants', participantsRoute);
server.use('/api/possible-dates', possibleDatesRoute);
server.use('/api/availibility', availibilityRoute);
server.use('/api/auth', authRoute);
server.get('/', (req, res) =>
res

View File

@ -2,5 +2,6 @@ module.exports = {
jwt_secret: process.env.JWT_SECRET,
port: process.env.PORT || 3001,
db_url: process.env.DATABASE_URL,
environment: process.env.NODE_ENV,
environment: process.env.NODE_ENV || 'development',
saltingRounds: process.env.SALTING_ROUNDS || 10,
};

36
helpers/authJwt.js Normal file
View File

@ -0,0 +1,36 @@
const jwt = require('jsonwebtoken');
const { jwt_secret } = require('../config/config');
module.exports = {
authenticate,
generateToken,
};
function generateToken(user) {
const payload = {
username: user.username,
email: user.email
};
const options = {
expiresIn: '30d',
};
return jwt.sign(payload, jwt_secret, options);
}
function authenticate(req, res, next) {
const token = req.get('Authorization');
if (token) {
jwt.verify(token, jwt_secret, (err, decoded) => {
if (err) return res.status(401).json(err);
req.decoded = decoded;
next();
});
} else {
return res.status(401).json({
error: 'No token provided, must be set on the Authorization Header',
});
}
}

96
package-lock.json generated
View File

@ -172,6 +172,11 @@
}
}
},
"buffer-equal-constant-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
"integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
},
"buffer-writer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
@ -400,6 +405,14 @@
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
},
"ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@ -1090,6 +1103,54 @@
"resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
"integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8="
},
"jsonwebtoken": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
"integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
"requires": {
"jws": "^3.2.2",
"lodash.includes": "^4.3.0",
"lodash.isboolean": "^3.0.3",
"lodash.isinteger": "^4.0.4",
"lodash.isnumber": "^3.0.3",
"lodash.isplainobject": "^4.0.6",
"lodash.isstring": "^4.0.1",
"lodash.once": "^4.0.0",
"ms": "^2.1.1",
"semver": "^5.6.0"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
"requires": {
"buffer-equal-constant-time": "1.0.1",
"ecdsa-sig-formatter": "1.0.11",
"safe-buffer": "^5.0.1"
}
},
"jws": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
"requires": {
"jwa": "^1.4.1",
"safe-buffer": "^5.0.1"
}
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@ -1192,6 +1253,41 @@
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
},
"lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
"integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
},
"lodash.isboolean": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
"integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
},
"lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
"integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
},
"lodash.isnumber": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
"integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
},
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
"integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
},
"lodash.once": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
"integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
},
"make-iterator": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",

View File

@ -19,6 +19,7 @@
"dotenv": "^8.2.0",
"express": "^4.17.1",
"helmet": "^3.22.0",
"jsonwebtoken": "^8.5.1",
"knex": "^0.21.1",
"pg": "^8.0.3",
"pgtools": "^0.3.0",