Reputation: 948
I do authorization and user registration on the server. In search I found a little guide https://www.techiediaries.com/nestjs-tutorial-jwt-authentication . Following him made registration and user authorization. My problem is that during registration the password is stored in the database in the clear.
After registration, the password is stored in clear text.
The controller and model do not differ from that in the manual that I cited above.
@Post('login')
async login(@Body() user: UserEntity): Promise<Object> {
return await this.authService.login(user);
}
@Post('register')
async register(@Body() user: UserEntity): Promise<Object> {
return await this.authService.register(user);
}
imports: [TypeOrmModule.forFeature([UserEntity])],
providers: [UserService, AuthService],
controllers: [AuthController],
I rewrote the user object for myself.
import { Entity, PrimaryGeneratedColumn, Column, BeforeInsert } from 'typeorm';
import { hash, compare } from 'bcryptjs';
@Entity('users')
export class UserEntity {
@PrimaryGeneratedColumn() id: number;
@Column({ type: 'varchar', nullable: false }) firstName: string;
@Column({ type: 'varchar', nullable: false }) lastName: string;
@Column({ type: 'varchar', nullable: false }) email: string;
@Column({ type: 'varchar', nullable: false }) password: string;
@BeforeInsert()
async hashPassword(): Promise<void> {
this.password = await hash(this.password, 10);
}
async comparePassword(attempt: string): Promise<boolean> {
return await compare(attempt, this.password);
}
}
I also rewrote the authorization service for myself.
public async login(user: UserEntity) {
const userData = await this.userService.findByEmail(user.email);
const result = user.comparePassword(user.password);
if (!result) {
return {
message: 'Password or email is incorrect',
status: 404,
};
}
return this.getInfo(userData);
}
public async register(user: UserEntity): Promise<Object> {
const userData = await this.userService.findByEmail(user.email);
if (userData) {
return {
message: 'A user with this email already exists.',
status: 404,
};
}
const newUser = await this.userService.create(user);
return this.getInfo(newUser);
}
private async getInfo(userData: UserEntity) {
const accessToken = this.getAccessToken(userData);
return {
accessToken,
userId: userData.id,
status: 200,
};
}
private getAccessToken(userData: UserEntity) {
return this.jwtService.sign({
userId: userData.id,
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email,
});
}
User service also left unchanged.
async findByEmail(email: string): Promise<UserEntity> {
return await this.userRepository.findOne({ where: { email } });
}
async findById(id: number): Promise<UserEntity> {
return await this.userRepository.findOne({ where: { id } });
}
async create(user: UserEntity): Promise<UserEntity> {
return await this.userRepository.save(user);
}
Where could I make a mistake and now why is the password stored in clear text? I almost did the documentation and the function that is done before writing to the database, but I understand it does not work.
Upvotes: 0
Views: 5270
Reputation: 5076
Accorrding the github issue
BeforeInsert is an instance-level method, you need an actual instance of User in order for it to be invoked (you can't reference this.password if there's no this)
You can try to do something like (if you don't want to store pure passwords in db):
async create(user: UserEntity): Promise<UserEntity> {
user.password = await hash(user.password, 10);
return await this.userRepository.save(user);
}
Upvotes: 1