diff --git a/.envexample b/.envexample index b34c63c..9cd0154 100644 --- a/.envexample +++ b/.envexample @@ -1,4 +1,5 @@ APP_PORT = 3001 +NODE_ENV = development DB_HOST = localhost DB_USER = root @@ -6,6 +7,7 @@ DB_PASSWORD = DB_NAME = adaptive_learning ACCESS_TOKEN_SECRET = +REFRESH_TOKEN_SECRET = RESET_PASSWORD_SECRET = EMAIL_USER = diff --git a/controllers/auth/auth.js b/controllers/auth/auth.js index b93ce40..89727f9 100644 --- a/controllers/auth/auth.js +++ b/controllers/auth/auth.js @@ -269,6 +269,12 @@ export const loginUser = async (req, res) => { { where: { ID: user.ID } } ); + res.cookie("refreshToken", refreshToken, { + httpOnly: true, + secure: process.env.NODE_ENV === "production", + sameSite: "Strict", + }); + const userResponse = { ID: user.ID, NAME_USERS: user.NAME_USERS, @@ -286,48 +292,68 @@ export const loginUser = async (req, res) => { }; export const refreshToken = async (req, res) => { - const { REFRESH_TOKEN } = req.body; + const refreshToken = req.cookies?.refreshToken || req.body.REFRESH_TOKEN; - if (!REFRESH_TOKEN) { + if (!refreshToken) { return response(400, null, "Refresh token is required!", res); } try { - const user = await models.User.findOne({ where: { REFRESH_TOKEN } }); + const user = await models.User.findOne({ + where: { REFRESH_TOKEN: refreshToken }, + }); if (!user) { return response(403, null, "Invalid refresh token!", res); } - jwt.verify( - REFRESH_TOKEN, - process.env.REFRESH_TOKEN_SECRET, - (err, decoded) => { - if (err) { - if (err.name === "TokenExpiredError") { - return response( - 401, - null, - "Refresh token expired. Please login again.", - res - ); - } - return response(403, null, "Invalid refresh token!", res); - } - - const newAccessToken = jwt.sign( - { ID: user.ID, ROLE: user.ROLE }, - process.env.ACCESS_TOKEN_SECRET, - { expiresIn: "3h" } - ); - - response( - 200, - { TOKEN: `Bearer ${newAccessToken}` }, - "Token refreshed successfully", + let decoded; + try { + decoded = jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET); + } catch (err) { + if (err.name === "TokenExpiredError") { + return response( + 401, + null, + "Refresh token expired. Please login again.", res ); } + return response(403, null, "Invalid refresh token!", res); + } + + if (decoded.ID !== user.ID) { + return response(403, null, "Invalid refresh token data!", res); + } + + const newAccessToken = jwt.sign( + { ID: user.ID, ROLE: user.ROLE }, + process.env.ACCESS_TOKEN_SECRET, + { expiresIn: "3h" } + ); + + const newRefreshToken = jwt.sign( + { ID: user.ID, ROLE: user.ROLE }, + process.env.REFRESH_TOKEN_SECRET, + { expiresIn: "7d" } + ); + + await models.User.update( + { REFRESH_TOKEN: newRefreshToken }, + { where: { ID: user.ID } } + ); + + res.cookie("refreshToken", newRefreshToken, { + httpOnly: true, + secure: process.env.NODE_ENV === "production", + sameSite: "Strict", + }); + + response( + 200, + { TOKEN: `Bearer ${newAccessToken}`, REFRESH_TOKEN: newRefreshToken }, + "Token refreshed successfully", + res ); } catch (error) { console.log(error);