S
S
Speakermen2021-11-21 09:26:58
JSON Web Token
Speakermen, 2021-11-21 09:26:58

Is LocalAuthGuard required for registration?

I don’t know if @UseGuards(LocalAuthGuard) is needed for registration, if I use it, then all logic crashes validation in dto has not yet been added

Login
If email and password are correct, access_token is returned
If email is correct and password is incorrect, 401 Email or password is incorrect Unauthorized
If email is incorrect but password is correct 401 Email or password is incorrect Unauthorized

Register
If email exists 409 Choose another email Conflict
If does not exist create user and return access_token

If using

@UseGuards(LocalAuthGuard)
  @Post('/register')

The whole logic crashes because I can’t check for the existence of email-a in local.strategy.ts, since when I login-e it will be that such an email already exists

. As I understand it, only user_id and role should be stored in access_token
.

@UseGuards(LocalAuthGuard)
  @Post('/login')
  async login(@ReqUser() reqUser) {
    return this.authService.login(reqUser);
  }


import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from '../auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({ usernameField: 'email' });
  }

  async validate(email: string, password: string): Promise<any> {
    const user = await this.authService.validateUser({ email, password });

    if (!user) {
      throw new UnauthorizedException('Email or password is incorrect');
    }

    await this.authService.validatePassport(password, user.password);

    return user;
  }
}


public async login(user): Promise<any> {
    return {
      access_token: this.jwtService.sign({
        username: user.username,
        sub: user.id,
      }),
    };
  }


When registering, I don’t need it in the controller @UseGuards(LocalAuthGuard)

All code

//auth.controller.ts
import { ReqBody } from './decorators/reqbody.decorator';
import {
  Body,
  Controller,
  Get,
  Post,
  UseGuards,
  ValidationPipe,
} from '@nestjs/common';
import { AuthService } from './auth.service';
import { CreateRegisterDto } from './dto/create-register.dto';
import { ReqUser } from './decorators/requser.decorator';
import { JwtAuthGuard } from './guards/jwt-auth.guard';
import { LocalAuthGuard } from './guards/local-auth.guard';

@Controller()
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @UseGuards(LocalAuthGuard)
  @Post('/login')
  async login(@ReqUser() reqUser) {
    return this.authService.login(reqUser);
  }

  /*
  @UseGuards(LocalAuthGuard)
  @Post('/register')
  async register(
    @ReqBody(new ValidationPipe({ validateCustomDecorators: true }))
    createRegisterDto: CreateRegisterDto,
  ) {
    return this.authService.register(createRegisterDto);
  }
  */

  @Post('/register')
  async register(@Body() createRegisterDto: CreateRegisterDto) {
    return this.authService.register(createRegisterDto);
  }

  @UseGuards(JwtAuthGuard)
  @Get('/profile')
  async profile(@ReqUser() reqUser) {
    return reqUser;
  }
}

//local.strategy.ts
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from '../auth.service';

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({ usernameField: 'email' });
  }

  async validate(email: string, password: string): Promise<any> {
    const user = await this.authService.validateUser({ email, password });

    if (!user) {
      throw new UnauthorizedException('Email or password is incorrect');
    }

    await this.authService.validatePassport(password, user.password);

    return user;
  }
}

//jwt.strategy.ts
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: process.env.JWT_SECRET,
    });
  }

  async validate(payload: any) {
    return { id: payload.sub, username: payload.username };
  }
}

//auth.service.ts
import { CreateLoginDto } from './dto/create-login.dto';
import { CreateRegisterDto } from './dto/create-register.dto';
import { UsersService } from './../users/users.service';
import {
  ConflictException,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { User as UserModel } from '@prisma/client';
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(
    private readonly usersService: UsersService,
    private readonly jwtService: JwtService,
  ) {}

  public async validateUser(createLoginDto: CreateLoginDto): Promise<any> {
    return await this.usersService.findOne({
      email: createLoginDto.email,
    });
  }

  public async validateEmail(email: string, inputEmail: string) {
    if (email === inputEmail) {
      throw new ConflictException('Choose another email');
    }
  }

  public async validatePassport(password: string, hash: string) {
    if (!(await bcrypt.compare(password, hash))) {
      throw new UnauthorizedException('Email or password is incorrect');
    }
  }

  public async login(user): Promise<any> {
    return {
      access_token: this.jwtService.sign({
        username: user.username,
        sub: user.id,
      }),
    };
  }

  public async register(createRegisterDto: CreateRegisterDto): Promise<any> {
    const user = await this.validateUser(createRegisterDto);

    if (user) {
      await this.validateEmail(user.email, createRegisterDto.email);
    }

    createRegisterDto.password = await bcrypt.hash(
      createRegisterDto.password,
      12,
    );

    const payload = await this.usersService.create(createRegisterDto);

    return {
      access_token: this.jwtService.sign({
        username: payload.username,
        sub: payload.id,
      }),
    };
  }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
L
lssssssssssl, 2021-11-21
@Speakermen

A local strategy is needed only for authentication (You can do without it by writing the same with pens).
Otherwise, jwt is a strategy.
Registration should not have a guard if the user is not yet in the database and there is nothing to check it for.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question