From 3eb644e7f2584af707b16fc97f6c6381a8abaf66 Mon Sep 17 00:00:00 2001 From: Hagop Jamkojian Date: Mon, 14 Sep 2020 22:48:58 +0200 Subject: [PATCH] Add tokens config --- src/config/tokens.js | 9 +++++++++ src/models/token.model.js | 3 ++- src/services/auth.service.js | 9 +++++---- src/services/token.service.js | 5 +++-- tests/integration/auth.test.js | 29 +++++++++++++++-------------- 5 files changed, 34 insertions(+), 21 deletions(-) create mode 100644 src/config/tokens.js diff --git a/src/config/tokens.js b/src/config/tokens.js new file mode 100644 index 00000000..495cbf35 --- /dev/null +++ b/src/config/tokens.js @@ -0,0 +1,9 @@ +const tokenTypes = { + ACCESS: 'access', + REFRESH: 'refresh', + RESET_PASSWORD: 'resetPassword', +}; + +module.exports = { + tokenTypes, +}; diff --git a/src/models/token.model.js b/src/models/token.model.js index dac615cc..fd8fb9b9 100644 --- a/src/models/token.model.js +++ b/src/models/token.model.js @@ -1,5 +1,6 @@ const mongoose = require('mongoose'); const { toJSON } = require('./plugins'); +const { tokenTypes } = require('../config/tokens'); const tokenSchema = mongoose.Schema( { @@ -15,7 +16,7 @@ const tokenSchema = mongoose.Schema( }, type: { type: String, - enum: ['refresh', 'resetPassword'], + enum: [tokenTypes.REFRESH, tokenTypes.RESET_PASSWORD], required: true, }, expires: { diff --git a/src/services/auth.service.js b/src/services/auth.service.js index 07571e78..6ef5eb63 100644 --- a/src/services/auth.service.js +++ b/src/services/auth.service.js @@ -3,6 +3,7 @@ const tokenService = require('./token.service'); const userService = require('./user.service'); const Token = require('../models/token.model'); const ApiError = require('../utils/ApiError'); +const { tokenTypes } = require('../config/tokens'); /** * Login with username and password @@ -24,7 +25,7 @@ const loginUserWithEmailAndPassword = async (email, password) => { * @returns {Promise} */ const logout = async (refreshToken) => { - const refreshTokenDoc = await Token.findOne({ token: refreshToken, type: 'refresh', blacklisted: false }); + const refreshTokenDoc = await Token.findOne({ token: refreshToken, type: tokenTypes.REFRESH, blacklisted: false }); if (!refreshTokenDoc) { throw new ApiError(httpStatus.NOT_FOUND, 'Not found'); } @@ -38,7 +39,7 @@ const logout = async (refreshToken) => { */ const refreshAuth = async (refreshToken) => { try { - const refreshTokenDoc = await tokenService.verifyToken(refreshToken, 'refresh'); + const refreshTokenDoc = await tokenService.verifyToken(refreshToken, tokenTypes.REFRESH); const user = await userService.getUserById(refreshTokenDoc.user); if (!user) { throw new Error(); @@ -58,12 +59,12 @@ const refreshAuth = async (refreshToken) => { */ const resetPassword = async (resetPasswordToken, newPassword) => { try { - const resetPasswordTokenDoc = await tokenService.verifyToken(resetPasswordToken, 'resetPassword'); + const resetPasswordTokenDoc = await tokenService.verifyToken(resetPasswordToken, tokenTypes.RESET_PASSWORD); const user = await userService.getUserById(resetPasswordTokenDoc.user); if (!user) { throw new Error(); } - await Token.deleteMany({ user: user.id, type: 'resetPassword' }); + await Token.deleteMany({ user: user.id, type: tokenTypes.RESET_PASSWORD }); await userService.updateUserById(user.id, { password: newPassword }); } catch (error) { throw new ApiError(httpStatus.UNAUTHORIZED, 'Password reset failed'); diff --git a/src/services/token.service.js b/src/services/token.service.js index 217b9e8d..b212dc7e 100644 --- a/src/services/token.service.js +++ b/src/services/token.service.js @@ -5,6 +5,7 @@ const config = require('../config/config'); const userService = require('./user.service'); const { Token } = require('../models'); const ApiError = require('../utils/ApiError'); +const { tokenTypes } = require('../config/tokens'); /** * Generate token @@ -68,7 +69,7 @@ const generateAuthTokens = async (user) => { const refreshTokenExpires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = generateToken(user.id, refreshTokenExpires); - await saveToken(refreshToken, user.id, refreshTokenExpires, 'refresh'); + await saveToken(refreshToken, user.id, refreshTokenExpires, tokenTypes.REFRESH); return { access: { @@ -94,7 +95,7 @@ const generateResetPasswordToken = async (email) => { } const expires = moment().add(config.jwt.resetPasswordExpirationMinutes, 'minutes'); const resetPasswordToken = generateToken(user.id, expires); - await saveToken(resetPasswordToken, user.id, expires, 'resetPassword'); + await saveToken(resetPasswordToken, user.id, expires, tokenTypes.RESET_PASSWORD); return resetPasswordToken; }; diff --git a/tests/integration/auth.test.js b/tests/integration/auth.test.js index 608ca6b4..c052ad53 100644 --- a/tests/integration/auth.test.js +++ b/tests/integration/auth.test.js @@ -12,6 +12,7 @@ const ApiError = require('../../src/utils/ApiError'); const setupTestDB = require('../utils/setupTestDB'); const { User, Token } = require('../../src/models'); const { roleRights } = require('../../src/config/roles'); +const { tokenTypes } = require('../../src/config/tokens'); const { userOne, admin, insertUsers } = require('../fixtures/user.fixture'); const { userOneAccessToken, adminAccessToken } = require('../fixtures/token.fixture'); @@ -127,7 +128,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh'); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH); await request(app).post('/v1/auth/logout').send({ refreshToken }).expect(httpStatus.NO_CONTENT); @@ -151,7 +152,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh', true); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH, true); await request(app).post('/v1/auth/logout').send({ refreshToken }).expect(httpStatus.NOT_FOUND); }); @@ -162,7 +163,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh'); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH); const res = await request(app).post('/v1/auth/refresh-tokens').send({ refreshToken }).expect(httpStatus.OK); @@ -172,7 +173,7 @@ describe('Auth routes', () => { }); const dbRefreshTokenDoc = await Token.findOne({ token: res.body.refresh.token }); - expect(dbRefreshTokenDoc).toMatchObject({ type: 'refresh', user: userOne._id, blacklisted: false }); + expect(dbRefreshTokenDoc).toMatchObject({ type: tokenTypes.REFRESH, user: userOne._id, blacklisted: false }); const dbRefreshTokenCount = await Token.countDocuments(); expect(dbRefreshTokenCount).toBe(1); @@ -186,7 +187,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = tokenService.generateToken(userOne._id, expires, 'invalidSecret'); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh'); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH); await request(app).post('/v1/auth/refresh-tokens').send({ refreshToken }).expect(httpStatus.UNAUTHORIZED); }); @@ -203,7 +204,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh', true); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH, true); await request(app).post('/v1/auth/refresh-tokens').send({ refreshToken }).expect(httpStatus.UNAUTHORIZED); }); @@ -212,7 +213,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().subtract(1, 'minutes'); const refreshToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh'); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH); await request(app).post('/v1/auth/refresh-tokens').send({ refreshToken }).expect(httpStatus.UNAUTHORIZED); }); @@ -220,7 +221,7 @@ describe('Auth routes', () => { test('should return 401 error if user is not found', async () => { const expires = moment().add(config.jwt.refreshExpirationDays, 'days'); const refreshToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(refreshToken, userOne._id, expires, 'refresh'); + await tokenService.saveToken(refreshToken, userOne._id, expires, tokenTypes.REFRESH); await request(app).post('/v1/auth/refresh-tokens').send({ refreshToken }).expect(httpStatus.UNAUTHORIZED); }); @@ -259,7 +260,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.resetPasswordExpirationMinutes, 'minutes'); const resetPasswordToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(resetPasswordToken, userOne._id, expires, 'resetPassword'); + await tokenService.saveToken(resetPasswordToken, userOne._id, expires, tokenTypes.RESET_PASSWORD); await request(app) .post('/v1/auth/reset-password') @@ -271,7 +272,7 @@ describe('Auth routes', () => { const isPasswordMatch = await bcrypt.compare('password2', dbUser.password); expect(isPasswordMatch).toBe(true); - const dbResetPasswordTokenCount = await Token.countDocuments({ user: userOne._id, type: 'resetPassword' }); + const dbResetPasswordTokenCount = await Token.countDocuments({ user: userOne._id, type: tokenTypes.RESET_PASSWORD }); expect(dbResetPasswordTokenCount).toBe(0); }); @@ -285,7 +286,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.resetPasswordExpirationMinutes, 'minutes'); const resetPasswordToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(resetPasswordToken, userOne._id, expires, 'resetPassword', true); + await tokenService.saveToken(resetPasswordToken, userOne._id, expires, tokenTypes.RESET_PASSWORD, true); await request(app) .post('/v1/auth/reset-password') @@ -298,7 +299,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().subtract(1, 'minutes'); const resetPasswordToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(resetPasswordToken, userOne._id, expires, 'resetPassword'); + await tokenService.saveToken(resetPasswordToken, userOne._id, expires, tokenTypes.RESET_PASSWORD); await request(app) .post('/v1/auth/reset-password') @@ -310,7 +311,7 @@ describe('Auth routes', () => { test('should return 401 if user is not found', async () => { const expires = moment().add(config.jwt.resetPasswordExpirationMinutes, 'minutes'); const resetPasswordToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(resetPasswordToken, userOne._id, expires, 'resetPassword'); + await tokenService.saveToken(resetPasswordToken, userOne._id, expires, tokenTypes.RESET_PASSWORD); await request(app) .post('/v1/auth/reset-password') @@ -323,7 +324,7 @@ describe('Auth routes', () => { await insertUsers([userOne]); const expires = moment().add(config.jwt.resetPasswordExpirationMinutes, 'minutes'); const resetPasswordToken = tokenService.generateToken(userOne._id, expires); - await tokenService.saveToken(resetPasswordToken, userOne._id, expires, 'resetPassword'); + await tokenService.saveToken(resetPasswordToken, userOne._id, expires, tokenTypes.RESET_PASSWORD); await request(app).post('/v1/auth/reset-password').query({ token: resetPasswordToken }).expect(httpStatus.BAD_REQUEST);