A new user is created without a jwt token. An empty token is returned
I don't understand what the problem is. Help me please. Himself frontend developer and backend for study. Don't scold too much) https://github.com/theDeemoonn/reex-backend
Service
import {
Injectable,
HttpException,
HttpStatus,
UnauthorizedException,
} from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { CreateUserDto } from '../users/dto/create-user.dto';
import { JwtService } from '@nestjs/jwt';
import * as bcrypt from 'bcryptjs';
import { User } from '../users/users.model';
@Injectable()
export class AuthService {
constructor(
private userService: UsersService,
private JwtService: JwtService,
) {}
async login(userDto: CreateUserDto) {
const user = await this.validateUser(userDto);
const tokens = await this.issueTokenPair(user);
return {
user: this.returnUserFields(user),
...tokens,
};
}
async registration(userDto: CreateUserDto) {
const candidate = await this.userService.getUserByEmail(userDto.email);
if (candidate) {
throw new HttpException(
'Пользователь с таким email уже существует',
HttpStatus.BAD_REQUEST,
);
}
const hashPassword = await bcrypt.hash(userDto.password, 6);
const user = await this.userService.createUser({
...userDto,
password: hashPassword,
});
const newUser = await user.save();
const tokens = await this.issueTokenPair(newUser);
return { user: this.returnUserFields(user), ...tokens };
}
private async validateUser(userDto: CreateUserDto) {
const user = await this.userService.getUserByEmail(userDto.email);
const passwordEquals = await bcrypt.compare(
userDto.password,
user.password,
);
if (!passwordEquals) {
throw new UnauthorizedException('Некорректный пароль');
}
if (user && passwordEquals) {
return user;
}
throw new UnauthorizedException('Некорректный email или пароль');
}
private async issueTokenPair(user: User) {
const payload = { email: user.email, id: user.id, roles: user.roles };
const refreshToken = await this.JwtService.signAsync(payload, {
expiresIn: '15d',
});
const accessToken = await this.JwtService.signAsync(payload, {
expiresIn: '1h',
});
return { refreshToken, accessToken };
}
returnUserFields(user: User) {
return {
_id: user.id,
email: user.email,
};
}
}
Controller
import {
Body,
Controller,
Post,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { CreateUserDto } from '../users/dto/create-user.dto';
import { AuthService } from './auth.service';
@ApiTags('Авторизация')
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
@UsePipes(new ValidationPipe())
@Post('/login')
async login(@Body() userDto: CreateUserDto) {
await this.authService.login(userDto);
}
@UsePipes(new ValidationPipe())
@Post('/registration')
async registration(@Body() userDto: CreateUserDto) {
await this.authService.registration(userDto);
}
}
Module
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UsersModule } from '../users/users.module';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './strategy/jwt.strategy';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { getJWTConfig } from './config/jwt.config';
@Module({
controllers: [AuthController],
providers: [AuthService, JwtStrategy],
imports: [
UsersModule,
ConfigModule,
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: getJWTConfig,
inject: [ConfigService],
}),
],
})
export class AuthModule {}
JwtStrategy
I thought that the problem was in .env wrote secretOrKey: ${process.env.SECRET_KEY}
did not work
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { User } from '../../users/users.model';
import { UsersService } from '../../users/users.service';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly configService: ConfigService,
private readonly usersService: UsersService,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: `${process.env.SECRET_KEY}`,
});
}
async validate(users: User) {
return await this.usersService.getUserById(users.id);
}
}
JWTConfig
import { ConfigService } from '@nestjs/config';
import { JwtModuleOptions } from '@nestjs/jwt';
export const getJWTConfig = async (
configService: ConfigService,
): Promise<JwtModuleOptions> => ({
secret: configService.get('SECRET_KEY'),
});
CreateUserDto
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@ApiProperty({ example: 'google@gmail.com', description: 'Почта' })
@IsEmail({}, { message: 'Некорректный email' })
readonly email: string;
@ApiProperty({ example: 'qwerty123456', description: 'Пароль' })
@MinLength(6, { message: 'Пароль должен быть больше 6 символов' })
@IsString()
readonly password: string;
@ApiProperty({ example: 'Иванов', description: 'Фамилия' })
readonly surname: string;
@ApiProperty({ example: 'Иван', description: 'Имя' })
readonly name: string;
@ApiProperty({ example: '20', description: 'Возраст' })
readonly age: number;
@ApiProperty({ example: '89999999999', description: 'Телефон' })
readonly phone: number;
}
You aren't returning anything in your controller, so the post succeeds but has nothing to send back to the client. Add return
before your await this.service.
whatever method calls