1. passport와 인증전략


jwt.guard.ts

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

// jwtGuard => jwtstrategy

흐름은 guard를 거쳐 strategy로 간다.

jwt.payload.ts

export type Payload = {
  email: string;
  sub: string;
};

jwt.strategy.ts

import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';
import { Payload } from './jwt.payload';
import { CatsRepository } from 'src/cats/cats.repository';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(private readonly catsRepository: CatsRepository) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), // Header의 token에서 추출
      secretOrKey: 'secret', // key, 유출되면 안됨, AuthModule의 JwtModule.register의 secret와 맞춰줘야한다.
      igonoreExpiration: false, // 만료되는 기간
    }); // jwt에 대한 설정
  }
  async validate(payload: Payload) {
    const cat = await this.catsRepository.findCatByIdWithoutPassword(
      payload.sub,
    );
    if (cat) {
      return cat; // request.user
    } else {
      throw new UnauthorizedException('접근 오류');
    }
  }
}

nest.js에서 validate 함수는 @nestjs/passport 모듈과 Passport 라이브러리의 통합의 일부로 자동으로 실행된다.

validate 함수가 사용자 객체를 반환하면, Passport는 이 객체를 현재 요청의 user 속성에 할당한다. 이를 통해 이후의 모든 컨트롤러나 서비스에서 **request.user**를 통해 인증된 사용자의 정보에 접근할 수 있다.

함수 findCatByIdWithoutPasswordrepository파일에 작성해보자

cats.repository.ts

import { HttpException, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Cat } from './cats.schema';
import { Model } from 'mongoose';
import { CatRequestDto } from './dto/cats.request.dto';

@Injectable()
export class CatsRepository {
  constructor(@InjectModel(Cat.name) private readonly catModel: Model<Cat>) {}

  async existsByEmail(email: string) {
    try {
      const result = await this.catModel.exists({ email });
      return result;
    } catch {
      throw new HttpException('db error', 400);
    }
  }
  async create(cat: CatRequestDto) {
    return await this.catModel.create(cat);
  }

  async findCatByEmail(email: string) {
    const cat = await this.catModel.findOne({ email });
    return cat;
  }

  async findCatByIdWithoutPassword(catId: string) {
    const cat = await this.catModel.findById(catId).select('-password'); // select로 password를 제외(-,마이너스)하고 가져온다. 보안상 이유로 가져오지 않는다.
    return cat;
  }
}

findByIdcatId에 해당하는 유저를 찾고 select로 해당 유저를 가져온다. 여기서는 select('-password')를 사용해서 password를 제외(-,마이너스)하고 가져오는데 password는 보안상 이유로 가져오지 않는다.