Add feature to generate refresh token

This commit is contained in:
AbegaM
2024-02-22 12:14:14 +03:00
parent 44ccb5dedd
commit 7ef3fd5f6b
7 changed files with 105 additions and 1 deletions

21
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"better-sqlite3": "^8.1.0",
"body-parser": "^1.20.2",
"check-password-strength": "^2.0.7",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
@@ -2583,6 +2584,26 @@
"node": ">= 0.6"
}
},
"node_modules/cookie-parser": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz",
"integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==",
"dependencies": {
"cookie": "0.4.1",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",

View File

@@ -31,6 +31,7 @@
"better-sqlite3": "^8.1.0",
"body-parser": "^1.20.2",
"check-password-strength": "^2.0.7",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",

View File

@@ -7,6 +7,7 @@ const {
checkPasswordStrength,
comparePasswords,
generateToken,
decodeToken,
} = require('../utils');
const createDefaultTables = async () => {
@@ -227,7 +228,7 @@ const obtainAccessToken = async (req, res) => {
const payload = {
username: user.username,
userId: user.id,
roleId: usersRole.role_id,
roleId: usersRole[0].role_id,
};
// generate an access token
@@ -259,9 +260,61 @@ const obtainAccessToken = async (req, res) => {
}
};
const refreshAccessToken = async (req, res) => {
try {
// extract the payload from the token and verify it
const payload = await decodeToken(
req.cookies.refreshToken,
config.jwtSecret,
);
// find the user
const users = rowService.get({
tableName: '_users',
whereString: 'WHERE id=?',
whereStringValues: [payload.userId],
});
if (users.length <= 0) {
return res.status(401).send({ message: 'User not found' });
}
const user = users[0];
const newPaylod = {
username: payload.username,
userId: payload.userId,
roleId: payload.roleId,
};
// generate an access token
const accessToken = await generateToken(
{ subject: 'accessToken', ...newPaylod },
config.jwtSecret,
'1H',
);
// generate a refresh token
const refreshToken = await generateToken(
{ subject: 'refreshToken', ...newPaylod },
config.jwtSecret,
config.jwtExpirationTime,
);
// set the token in the cookie
let cookieOptions = { httpOnly: true, secure: false, Path: '/' };
res.cookie('accessToken', accessToken, cookieOptions);
res.cookie('refreshToken', refreshToken, cookieOptions);
res.status(201).send({ message: 'Success', data: { userId: user.id } });
} catch (error) {
res.status(401).send({ message: 'Invalid refresh token' });
}
};
module.exports = {
createDefaultTables,
updateUser,
registerUser,
obtainAccessToken,
refreshAccessToken,
};

View File

@@ -7,6 +7,7 @@ const expressWinston = require('express-winston');
const cors = require('cors');
const rateLimit = require('express-rate-limit');
const swaggerUi = require('swagger-ui-express');
const cookieParser = require('cookie-parser');
const config = require('./config/index');
const db = require('./db/index');
@@ -29,6 +30,7 @@ app.get('/health', (req, res) => {
});
app.use(bodyParser.json());
app.use(cookieParser());
// Activate wal mode
db.exec('PRAGMA journal_mode = WAL');

View File

@@ -11,4 +11,10 @@ router.post(
controllers.obtainAccessToken,
);
router.get(
'/token/refresh',
validator(schema.refreshAccessToken),
controllers.refreshAccessToken,
);
module.exports = router;

View File

@@ -12,6 +12,13 @@ const obtainAccessToken = Joi.object({
}).required(),
});
const refreshAccessToken = Joi.object({
query: Joi.object().required(),
params: Joi.object({}).required(),
body: Joi.object({}).required(),
});
module.exports = {
obtainAccessToken,
refreshAccessToken,
};

View File

@@ -468,6 +468,20 @@
}
}
}
},
"/api/auth/token/refresh": {
"get": {
"description": "",
"parameters": [],
"responses": {
"400": {
"description": "Bad Request"
},
"401": {
"description": "Unauthorized"
}
}
}
}
},
"definitions": {