자바스크립트로 구현하는 NestJS 앱의 사용자 인증과 권한 부여

NestJS는 Node.js 기반의 프레임워크로, 빠르고 확장 가능한 애플리케이션을 구축하기 위한 기능을 제공합니다. NestJS 앱에서 사용자 인증과 권한 부여를 구현하는 것은 매우 중요한 요소입니다. 이를 위해 자바스크립트를 사용하여 NestJS 앱에서 사용자 인증과 권한 부여를 어떻게 구현할 수 있는지 알아보겠습니다.

사용자 인증 구현하기

사용자 인증은 사용자가 앱에 로그인할 수 있는지 여부를 확인하는 과정입니다. 기본적으로 사용자를 인증하기 위해서는 사용자의 아이디와 비밀번호를 확인해야 합니다. NestJS에서는 주로 Passport와 같은 인기 있는 인증 미들웨어를 사용하여 사용자 인증을 구현합니다.

  1. 먼저 @nestjs/passport 패키지와 필요한 인증 전략 패키지를 설치합니다.
npm install --save @nestjs/passport passport passport-local
  1. AuthModule을 생성합니다.
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { LocalStrategy } from './local.strategy';
import { UsersModule } from '../users/users.module';
import { PassportModule } from '@nestjs/passport';

@Module({
  imports: [UsersModule, PassportModule],
  providers: [AuthService, LocalStrategy],
  controllers: [AuthController],
})
export class AuthModule {}
  1. AuthService를 생성하고 validateUser 메서드를 구현합니다.
import { Injectable } from '@nestjs/common';
import { UsersService } from '../users/users.service';

@Injectable()
export class AuthService {
  constructor(private usersService: UsersService) {}

  async validateUser(username: string, password: string): Promise<any> {
    const user = await this.usersService.findByUsername(username);
    if (user && user.password === password) {
      const { password, ...result } = user;
      return result;
    }
    return null;
  }
}
  1. LocalStrategy를 생성하고 validate 메서드를 구현합니다.
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-local';
import { AuthService } from './auth.service';

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

  async validate(username: string, password: string): Promise<any> {
    return this.authService.validateUser(username, password);
  }
}
  1. 사용자 인증을 위한 컨트롤러 AuthController를 생성합니다.
import { Controller, Request, Post, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { AuthService } from './auth.service';

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

  @UseGuards(AuthGuard('local'))
  @Post('login')
  async login(@Request() req) {
    return this.authService.login(req.user);
  }
}
  1. AuthGuard를 사용하여 인증이 필요한 라우트에 대한 인증을 하도록 설정합니다.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}

사용자 인증 구현을 위한 기본 단계는 위와 같습니다. 사용자 인증을 구현해놓으면, 로그인한 사용자만 특정 라우트에 접근할 수 있도록 설정할 수 있습니다.

권한 부여 구현하기

사용자 인증과 함께 권한 부여는 사용자가 특정 리소스에 접근할 수 있는지 여부를 제어하는 과정입니다. NestJS에서는 Guards를 사용하여 권한 부여를 구현할 수 있습니다.

  1. RolesGuard를 생성하고 canActivate 메서드를 구현합니다.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const roles = this.reflector.get<string[]>('roles', context.getHandler());
    if (!roles) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const hasRole = () => user.roles.some((role) => roles.includes(role));
    return user && hasRole();
  }
}
  1. UseGuards 데코레이터를 사용하여 권한 부여 규칙을 적용할 수 있는 라우트에 RolesGuard를 적용합니다.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { RolesGuard } from './roles.guard';
import { Roles } from './roles.decorator';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Roles('admin')
  @UseGuards(RolesGuard)
  @Get('admin')
  getAdminHello(): string {
    return this.appService.getAdminHello();
  }
}

Roles 데코레이터는 각 라우트에 필요한 권한을 정의하고, RolesGuard는 해당 권한이 있는 사용자만 접근할 수 있도록 설정합니다.

마치며

NestJS 앱에서 사용자 인증과 권한 부여는 중요한 요소입니다. NestJS에서는 Passport와 Guards를 활용하여 사용자 인증과 권한 부여를 쉽게 구현할 수 있습니다. 이를 통해 보안적인 측면을 강화하고 권한이 필요한 리소스에 대해 접근을 제한할 수 있습니다.

더 자세한 정보는 NestJS 공식 문서를 참조하시기 바랍니다.

참고 자료