Skip to content

Commit

Permalink
Add tokens config
Browse files Browse the repository at this point in the history
  • Loading branch information
hagopj13 committed Sep 14, 2020
1 parent 1650bdf commit 3eb644e
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 21 deletions.
9 changes: 9 additions & 0 deletions src/config/tokens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const tokenTypes = {
ACCESS: 'access',
REFRESH: 'refresh',
RESET_PASSWORD: 'resetPassword',
};

module.exports = {
tokenTypes,
};
3 changes: 2 additions & 1 deletion src/models/token.model.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const mongoose = require('mongoose');
const { toJSON } = require('./plugins');
const { tokenTypes } = require('../config/tokens');

const tokenSchema = mongoose.Schema(
{
Expand All @@ -15,7 +16,7 @@ const tokenSchema = mongoose.Schema(
},
type: {
type: String,
enum: ['refresh', 'resetPassword'],
enum: [tokenTypes.REFRESH, tokenTypes.RESET_PASSWORD],
required: true,
},
expires: {
Expand Down
9 changes: 5 additions & 4 deletions src/services/auth.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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');
}
Expand All @@ -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();
Expand All @@ -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');
Expand Down
5 changes: 3 additions & 2 deletions src/services/token.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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: {
Expand All @@ -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;
};

Expand Down
29 changes: 15 additions & 14 deletions tests/integration/auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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);

Expand All @@ -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);
});
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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);
});
Expand All @@ -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);
});
Expand All @@ -212,15 +213,15 @@ 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);
});

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);
});
Expand Down Expand Up @@ -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')
Expand All @@ -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);
});

Expand All @@ -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')
Expand All @@ -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')
Expand All @@ -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')
Expand All @@ -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);

Expand Down

0 comments on commit 3eb644e

Please sign in to comment.