NestJS 활용하기(5) - JWT, Passport

이태훈·2023년 11월 5일
0

NestJS

목록 보기
5/6

인증

인증 방식에는 크게 쿠키-세션 방식과 jwt 방식이 있는데, 여기서는 jwt 방식을 사용했다. 그리고 NestJS의 Passport 모듈(인증을 위한 미들웨어)를 활용하여 인증을 구현했다.

설치 방법

npm install @nestjs/jwt @nestjs/passport passport passport-jwt

사용 방법

1. jwt 모듈 등록

먼저 auth.module.ts에 jwt 모듈을 등록해준다. 이때 jwt에서 seceretKey로 사용할 값과 만료 시간등의 정보를 지정해준다.

    JwtModule.register({
      secret: process.env.JWT_SECRET || jwtConfig.secret,
      signOptions: {
        expiresIn: jwtConfig.expiresIn,
      }
    })

이 부분을 imports의 리스트에 넣어준다.

2. passport strategy 설정

starategy 설정을 위해 PassportStrategy 클래스를 확장하는 클래스를 생성한다. 이때 super를 통해 PassportStrategy 클래스를 설정해줘야 하며 validate 메서드를 구현해야 한다.

import { Strategy, ExtractJwt } from 'passport-jwt';

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

  async validate(payload: any) {
	// 데이터베이스와 연동하여 user가 있는지 확인
  }
}

3. passport module 등록

jwt 모듈과 마찬가지로 AuthModule에 등록을 해야 한다. 이때 기본 strategy는 jwt를 사용하기 때문에 jwt로 설정한다.

PassportModule.register({ defaultStrategy: 'jwt'})

이 부분을 imports 리스트에 추가해준다.

그리고 providers 리스트에 아까 생성한 JwtStrategy 클래스를 추가해주고 exports 리스트에 PassportMoudule을 추가하여 authModule을 import하는 다른 모듈에서 PassportMoudule을 사용할 수 있도록 해준다.

  providers: [AuthService, UserRepository, JwtStrategy],
  exports: [PassportModule]

4. Guards 미들웨어 사용

AuthGuard를 사용하여 인증을 요구하도록 설정한다. 이때 Board controller 전체에 인증을 요구하도록 설정하기 위해 controller를 선언할 때 UseGuards() 데코레이터를 사용한다.

import { AuthGuard } from '@nestjs/passport'; // 이 부분 추가

@Controller('board')
@UseGuards(AuthGuard())
export class BoardsController {
  // 기존 controller 내용
}

이때 AuthGuard('jwt')를 통해 명시적으로 jwt의 strategry를 사용한다고 설정할 수 있지만 현재 기본 strategy를 jwt로 설정했기 때문에 생략했다.

그리고 boardModule에서 authModule을 사용했으니, board.module.ts에 authModule을 import 해준다.

imports:[AuthModule],

이렇게 하고 나면 이제 jwt를 활용한 인증을 사용할 수 있다. HTTP 요청의 Authroization 헤더에 "Bearer " + 토큰의 형태로 전송을 하게 되면 이 토큰의 값을 통해 인증을 진행하게 된다.

이제 이 토큰의 값을 클라이언트에 제공하기 위해 로그인 부분에 accessToken을 생성하여 반환하는 부분을 추가한다.

import { JwtService } from '@nestjs/jwt'; // 이 부분 추가

@Injectable()
export class AuthService {
  constructor(
    private UserRepository: UserRepository,
    private jwtService: JwtService) {} // 이부분 추가
    
// 회원가입

// 로그인
  async singin(authCredentialDto: AuthCredentialDto): Promise<{accessToken: string}> {
    const { username, password } = authCredentialDto;

    if (// 유저가 존재하고 비밀번호가 일치하면) {
      const payload = { username };
      const accessToken = await this.jwtService.sign(payload);

      return { accessToken };
    } else {
      throw new UnauthorizedException('login failed');
    }
  }

위와 같이 jwtService를 선언하고 sign 메서드를 통해 원하는 정보를 담은 payload의 값을 이용하여 accessToken을 생성하고 클라이언트에게 반환한다. 클라이언트는 이렇게 받은 accessToken을 인증이 필요한 경우 요청과 함께 위에서 설명한 것처럼 전송하면 된다.

profile
지속가능한 개발자를 꿈꿉니다

0개의 댓글