Environment: Nest.js, Passport. Js, MongoDB
Note the points that need attention as follows
1 registration
During user registration, passwords need to be hashed. Plaintext passwords cannot be directly saved in the database. When querying users, passwords do not need to be queried and returned to the front end.
Hash using bcrypt
The complete user model is shown below
import { prop, modelOptions } from '@typegoose/typegoose'
import { ApiProperty } from '@nestjs/swagger'
import { hashSync } from 'bcryptjs'
@modelOptions({
schemaOptions: {
timestamps: true}})export class User {
@ApiProperty({ description: 'Username'.example: 'user1'})
@prop()
username: string
@ApiProperty({ description: 'password'.example: 'pass1'})
@prop({
select: false,
get(val){
return val
},
set(val){
return val ? hashSync(val): val
}
})
password: string
}
Copy the code
2 the login
During login, the server verifies the user name and password and returns a token
Verify using the Passport’s local policy
import { Strategy, IStrategyOptions } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport'
import { StrategyOptions } from 'passport-jwt';
import { InjectModel } from 'nestjs-typegoose';
import { User } from '@libs/db/models/user.model';
import { ReturnModelType } from '@typegoose/typegoose';
import { BadRequestException } from '@nestjs/common';
import { compareSync } from 'bcryptjs'
export class localStrategy extends PassportStrategy(Strategy, 'local'){
constructor(
@InjectModel(User) private userModel: ReturnModelType<typeof User>
){
super({
usernameField: 'username'.passwordField: 'password'
} as IStrategyOptions)
}
async validate(username: string, password: string){
const user = await this.userModel.findOne({username: username}).select('+password');
if(! user) {throw new BadRequestException('Incorrect username');
}
if(! compareSync(password,user.password)){throw new BadRequestException('Incorrect password');
}
returnuser; }}Copy the code
Returns the token after a successful login
@Post('login')
@ApiOperation({summary: 'login'})
@UseGuards(AuthGuard('local'))
async login(@Body() dto: LoginDto, @CurrentUser() user: DocumentType<User>){
return {
token: this.jwtService.sign(String(user._id))
};
}
Copy the code
3 User Authentication
Verify using Passport’s JWT policy
Step 1: Take out the token
Step 2: Search for the user based on the extracted ID
import { Strategy, StrategyOptions, ExtractJwt } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport'
import { InjectModel } from 'nestjs-typegoose';
import { User } from '@libs/db/models/user.model';
import { ReturnModelType } from '@typegoose/typegoose';
import { BadRequestException } from '@nestjs/common';
import { compareSync } from 'bcryptjs'
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt'){
constructor(
@InjectModel(User) private userModel: ReturnModelType<typeof User>
){
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.SECRET
} as StrategyOptions)
}
async validate(id){
return await this.userModel.findById(id)
}
}
Copy the code