From 6d993b0a9b3132a4074cd0f8bc0f1f66af8ce902 Mon Sep 17 00:00:00 2001 From: jannyHou Date: Wed, 30 Jan 2019 13:17:18 -0500 Subject: [PATCH] fix: hash the password Signed-off-by: jannyHou --- src/utils/user.authentication.ts | 16 +++++++++-- test/acceptance/user.controller.acceptance.ts | 27 ++++++++++++------- test/unit/utils.authentication.unit.ts | 4 +++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/utils/user.authentication.ts b/src/utils/user.authentication.ts index 160950844..6e0f910c4 100644 --- a/src/utils/user.authentication.ts +++ b/src/utils/user.authentication.ts @@ -10,6 +10,8 @@ import {promisify} from 'util'; import * as isemail from 'isemail'; import {HttpErrors} from '@loopback/rest'; import {UserProfile} from '@loopback/authentication'; +import {compare} from 'bcryptjs'; +const compareAsync = promisify(compare); const jwt = require('jsonwebtoken'); const signAsync = promisify(jwt.sign); const verifyAsync = promisify(jwt.verify); @@ -18,11 +20,21 @@ export async function getAccessTokenForUser( userRepository: UserRepository, credentials: Credentials, ): Promise { + console.log('getAccessTokenForUser', credentials.password); const foundUser = await userRepository.findOne({ - where: {email: credentials.email, password: credentials.password}, + where: {email: credentials.email}, }); if (!foundUser) { - throw new HttpErrors.Unauthorized('Wrong credentials!'); + throw new HttpErrors.Unauthorized( + `User with email ${credentials.email} not found`, + ); + } + const passwordMatched = await compareAsync( + credentials.password, + foundUser.password, + ); + if (!passwordMatched) { + throw new HttpErrors.Unauthorized('The credential is not correct!'); } const currentUser = _.pick(toJSON(foundUser), ['id', 'email', 'firstName']); diff --git a/test/acceptance/user.controller.acceptance.ts b/test/acceptance/user.controller.acceptance.ts index b9b121168..14a6f16a4 100644 --- a/test/acceptance/user.controller.acceptance.ts +++ b/test/acceptance/user.controller.acceptance.ts @@ -12,8 +12,11 @@ import {setupApplication} from './helper'; import {createRecommendationServer} from '../../recommender'; import {Server} from 'http'; import * as _ from 'lodash'; +import {promisify} from 'util'; +import {hash} from 'bcryptjs'; import {getAccessTokenForUser} from '../../src/utils/user.authentication'; const recommendations = require('../../recommender/recommendations.json'); +const hashAsync = promisify(hash); describe('UserController', () => { let app: ShoppingApplication; @@ -135,28 +138,32 @@ describe('UserController', () => { }); describe('authentication functions', () => { - // TODO: fix storing the plain password in the following issue: - // https://github.com/strongloop/loopback-next/issues/1996 + let plainPassword: string; + + before('create new user', async () => { + plainPassword = user.password; + // Salt + Hash Password + user.password = await hashAsync(user.password, 10); + }); + it('login returns a valid token', async () => { const newUser = await userRepo.create(user); await client .post('/users/login') - .send({email: newUser.email, password: newUser.password}) + .send({email: newUser.email, password: plainPassword}) .expect(200) - .then(getToken); + .then(verifyToken); - function getToken(res: Response) { + function verifyToken(res: Response) { const token = res.body.token; expect(token).to.not.be.empty(); } }); it('login returns an error when invalid credentials are used', async () => { - const newUser = await userRepo.create(user); - newUser.password = 'wrong password'; await client .post('/users/login') - .send({email: newUser.email, password: newUser.password}) + .send({email: user.email, password: 'wrongpassword'}) .expect(401); }); @@ -164,7 +171,7 @@ describe('UserController', () => { const newUser = await userRepo.create(user); const token = await getAccessTokenForUser(userRepo, { email: newUser.email, - password: newUser.password, + password: plainPassword, }); newUser.id = newUser.id.toString(); @@ -180,7 +187,7 @@ describe('UserController', () => { const newUser = await userRepo.create(user); await getAccessTokenForUser(userRepo, { email: newUser.email, - password: newUser.password, + password: plainPassword, }); await client.get('/users/me').expect(401); diff --git a/test/unit/utils.authentication.unit.ts b/test/unit/utils.authentication.unit.ts index 75d59a43b..678a22a33 100644 --- a/test/unit/utils.authentication.unit.ts +++ b/test/unit/utils.authentication.unit.ts @@ -12,6 +12,9 @@ import { import {UserRepository, OrderRepository} from '../../src/repositories'; import {User} from '../../src/models'; import * as _ from 'lodash'; +import {promisify} from 'util'; +import {hash} from 'bcryptjs'; +const hashAsync = promisify(hash); const SECRET = 'secretforjwt'; describe('authentication', () => { @@ -27,6 +30,7 @@ describe('authentication', () => { let newUser: User; before('create user', async () => { + user.password = await hashAsync(user.password, 10); newUser = await userRepo.create(user); });