[nest.js] Passport local 로그인

김민재·2024년 4월 25일

nest.js

목록 보기
20/63
  • 필요한 모듈 설치
    @nestjs/passport
    passport
    passport-local
    -D @types/passport-local

1. passport 폴더 생성

2. module에 불러오고 코드를 작성한다.

// auth.module.ts
@Module({
  imports: [TypeOrmModule.forFeature([User]), UserModule, PassportModule],
  providers: [AuthService, UserService, LocalStrategy],
  exports: [AuthService],
})

// auth.service.ts
  constructor(private readonly userService: UserService) {}

  // user를 확인한다.
  
  // user를 startegy를 이용해 req.user에 전달해준다.
  async validateUser(username: string, password: string) {
    const user = await this.userService.getUser(username);

    if (!user) {
      return '존재하지 않는 유저입니다.';
    }

    const signin = await compare(password, user.password);

    if (signin) {
      return user;
    } else {
      // passport 동작 규칙으로 맞추기 위해서 null을 반환한다.
      return null;
    }
  }
  
// auth.strategy.ts
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { AuthService } from './auth.service';
import { UnauthorizedException } from '@nestjs/common';

// passport를 사용할 때는 전략 파일을 생성해야된다.
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super();
  }

    async validate(username: string, password: string) {
    const user = await this.authService.validateUser(username, password);
    if (!user) {
      throw new UnauthorizedException();
    }

    return user;
  }
}

// 컨트롤러 사용
  // passport에서 사용한다.
  // guard를 'local'로 명시적으로 가능하지만 파일을 따로 만들어서도 가능하다 2-1
  @UseGuards(AuthGuard('local'))
  @Post('login')
  async login(@Request() req) {
    return req.user;
  }

2-1. guard 'local' 파일로 분리

  • 파일 생성

  • 코드 작성

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

// guard 'local' 명시를 파일로 분리
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}

// 컨트롤러
  // passport에서 사용한다.
  @UseGuards(LocalAuthGuard)
  @Post('login')
  async login(@Request() req) {
    return req.user;
  }

3. passport jwt 토큰 생성

  • 모듈 설치
    @nestjs/jwt passport-jwt @types/passport-jwt

  • jwt 모듈 설정

// auth.module.ts
  ConfigModule.forRoot(), // env
    JwtModule.register({
      secret: process.env.JWT_KEY,
      signOptions: {
        expiresIn: '1h',
      },
    }),
  • jwt 토큰 생성
// auth.service.ts
 async login(user: User) {
    const payload = {
      username: user.username,
      name: user.name,
    };

    return { accessToken: this.jwtService.sign(payload) };
  }
  
  • controller에서 설정
  // passport에서 사용한다.
  @UseGuards(LocalAuthGuard)
  @Post('login')
  async login(@Request() req) {
    return this.authService.login(req.user);
  }

4. jwt 토큰을 이용한 내 정보

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

// jwt token 검증 후 정보 반환
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: process.env.JWT_KEY,
    });
  }

  async validate(payload: { username: string; name: string }) {
    return payload;
  }
}



// jwt-auth.guard.ts
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

// jwt token 구분
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

  @UseGuards(JwtAuthGuard)
  @Get('me')
  async me(@Request() req) {
    console.log('ha');
    return req.user;
  }


// auth.module.ts
 providers: [AuthService, UserService, LocalStrategy, JwtStrategy],
profile
개발 경험치 쌓는 곳

0개의 댓글