summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorGravatar Piotr Russ <mail@pruss.it> 2020-11-22 13:49:09 +0100
committerGravatar Piotr Russ <mail@pruss.it> 2020-11-22 13:49:09 +0100
commit4569b85489e863465395f84e995dd3fdc44471b4 (patch)
tree6e4d27883809c94c8b3f3b87159d85c7f3874bbd /server
parent81ddf9b700bc48a1f8e472209f080f9c1d9a9b09 (diff)
downloadwebsite_creator-4569b85489e863465395f84e995dd3fdc44471b4.tar.gz
website_creator-4569b85489e863465395f84e995dd3fdc44471b4.tar.bz2
website_creator-4569b85489e863465395f84e995dd3fdc44471b4.zip
implement refresh tokens
Diffstat (limited to 'server')
-rw-r--r--server/middleware/auth.js30
-rw-r--r--server/models/User.js31
-rw-r--r--server/routes/user.js25
3 files changed, 61 insertions, 25 deletions
diff --git a/server/middleware/auth.js b/server/middleware/auth.js
index 42d93a4..462b100 100644
--- a/server/middleware/auth.js
+++ b/server/middleware/auth.js
@@ -9,16 +9,32 @@ const auth = async (req, res, next) => {
throw new Error();
}
- const decoded = jwt.verify(token, 'replaceThisWithSecretString');
- const user = await User.findOne({ _id: decoded._id, 'tokens.token': token });
+ try {
+ const decoded = jwt.verify(token, 'replaceThisWithSecretString');
+ req.userId = decoded._id;
+ req.refreshToken = decoded.ref;
+ return next();
+ } catch(er) {
+ if (er.message && er.message === 'jwt expired') {
+ const { _id, ref } = jwt.decode(token, 'replaceThisWithSecretString');
+ const user = await User.findById(_id);
+
+ if (!user) {
+ throw new Error();
+ }
+
+ if (user.sessions.filter(s => s.ref === ref).length > 0) {
+ req.userId = _id;
+ req.refreshToken = ref;
+ req.newToken = await user.generateJwtToken(res.req.refreshToken);;
+ return next();
+ }
+
+ throw new Error();
+ }
- if (!user) {
throw new Error();
}
-
- req.token = token;
- req.user = user;
- next();
} catch (err) {
res.redirect('/login');
}
diff --git a/server/models/User.js b/server/models/User.js
index 4fa6ffe..e777878 100644
--- a/server/models/User.js
+++ b/server/models/User.js
@@ -1,5 +1,6 @@
const mongoose = require("mongoose");
const bcrypt = require('bcryptjs');
+const randtoken = require('rand-token');
const jwt = require('jsonwebtoken');
const userSchema = new mongoose.Schema({
@@ -23,22 +24,36 @@ const userSchema = new mongoose.Schema({
min: 4,
max: 1024,
},
- tokens: [{
- token: {
+ sessions: [{
+ ref: {
type: String,
required: true
}
}]
});
-userSchema.methods.generateAuthToken = async function () {
- const user = this;
- const token = jwt.sign({ _id: user._id.toString() }, 'replaceThisWithSecretString')
+userSchema.methods.generateJwtToken = async function (currentRef) {
+ const ref = currentRef ? currentRef : randtoken.uid(256);
+
+ if (!currentRef) {
+ this.sessions = this.sessions.concat({ ref });
+ this.save();
+ }
+
+ return jwt.sign(
+ { _id: this._id.toString(), ref },
+ 'replaceThisWithSecretString',
+ { expiresIn: 300 }
+ );
+}
- user.tokens = user.tokens.concat({ token });
- user.save();
+userSchema.methods.endSession = async function (ref) {
+ this.sessions = this.sessions.filter((session) => {
+ return session.ref !== ref;
+ });
- return token;
+ await this.save();
+ return null;
}
userSchema.statics.findByCredentials = async (email, password) => {
diff --git a/server/routes/user.js b/server/routes/user.js
index d1100bc..b3bdee3 100644
--- a/server/routes/user.js
+++ b/server/routes/user.js
@@ -1,14 +1,19 @@
const router = require('express').Router();
const User = require('../models/User');
const auth = require('../middleware/auth');
+const jwt = require('jsonwebtoken');
+
+router.get('/me', auth, async (req, res) => {
+ const user = await User.findById(req.userId);
+ res.json({ email: user.email });
+})
router.post('/register', async (req, res) => {
const user = new User(req.body);
try {
await user.save();
- const token = await user.generateAuthToken();
- res.status(201).send({ user, token });
+ res.status(201).send({ email: user.email });
} catch(err) {
if (err._message) {
res.status(422).send(err._message);
@@ -23,10 +28,10 @@ router.post('/register', async (req, res) => {
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email, req.body.password);
- const token = await user.generateAuthToken();
+ const token = await user.generateJwtToken();
res
.cookie('token', token, {
- expires: new Date(Date.now() + 604800000),
+ maxAge: 604800000,
secure: false,
httpOnly: true,
})
@@ -39,12 +44,12 @@ router.post('/login', async (req, res) => {
router.post('/logout', auth, async (req, res) => {
try {
- req.user.tokens = req.user.tokens.filter((token) => {
- return token.token !== req.token;
- });
- await req.user.save();
-
- res.status(204).send();
+ const user = await User.findById(req.userId);
+ await user.endSession(req.refreshToken);
+ res
+ .clearCookie('token')
+ .status(204)
+ .send();
} catch (err) {
res.status(500).send();
}