uju's Tech

[Nest.js] Passport local strategy 본문

Nest

[Nest.js] Passport local strategy

ujusy 2021. 9. 9. 20:20

<본 포스팅은 기록용으로 작성되었습니다. 혹시 틀린 부분이 있거나 문제가 되는 부분이 있다면 답글 달아주세요!>


Passport local strategy

  • passport 에서의 local strategy는 가장 기본적인 email 과 password 를 가지고 인증하는것이다. (로그인할 때 사용됨)

nest 에서도 @nest/passport 와 passport-local 을 사용하여 local strategy를 구현할 수 있다.

들어가기전 일단..local strategy가 동작하는 흐름 보기.

  1. id , password 로 로그인 요청
  2. AuthGuard 를 통해 사용자 인증
  3. AuthGuard 가 호출되면 LocalStrategy 의 validate 호출
  4. 유저가 인증되면 AuthGuard 의 canActivate 가 true 리턴

Step1. 라이브러리 설치

$ npm install --save @nestjs/passport passport passport-local
$ npm install --save-dev @types/passport-local

Step2. local.strategy.ts 구현

auth 에 local.strategy.ts 구현

** 주의 **

공식 문서에는 usernameField, passwordField 작성되어 있지 않은데 아래와 같이 명시해주지 않으면 validate를 정상적으로 호출하지 못합니다.

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) {
// 내부에 필드 작성하는거 잊지말기.......문서 예시에는 안써있는데 안써주면
// validate가 호출되지 않습니다..
    super({ usernameField: 'email', passwordField: 'password' }); 
  }

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

    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

auth의 service에 위에서 사용할 validateUser 구현

import { Injectable } from '@nestjs/common';
import { UserService } from '../user/user.service';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../user/entities/user.entity';
import * as bcrypt from 'bcrypt';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(User) private usersRepository: Repository<User>,
  ) {}

  async validateUser(email: string, pass: string): Promise<any> {
    const user = await this.usersRepository.findOne({
      where: { email },
    });

    const password = await bcrypt.compare(pass, user.password);
    if (password) {
      const { password, ...userWithoutPassword } = user;
      return userWithoutPassword;
    }
    return null;
  }
}

auth.module.ts에 passportModul, localStrategy 추가

import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UserModule } from '../user/user.module';
import { PassportModule } from '@nestjs/passport';
import { LocalStrategy } from './local.strategy';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '../user/entities/user.entity';

@Module({
  imports: [UserModule, PassportModule, TypeOrmModule.forFeature([User])],
  providers: [AuthService, LocalStrategy],
  exports: [AuthService],
})
export class AuthModule {}
Comments