Nest.js를 이용한 OAuth 2.0 구현

윤진원·2023년 2월 12일
2

nest.js

목록 보기
1/1
post-thumbnail

OAuth가 뭔데?

이번에 연구실 홈페이지를 만들어 보면서, 로그인 관련 기능은 OAuth를 통해 구현하라는 과제가 주어졌다.
따라서, 개념부터 알아보자!

OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다.

위키 백과에 나와있는 개념이지만, 너무 어렵다!
쉽게 얘기하면 ID, 비밀 번호를 따로 입력하여 가입하지 않아도 원래 있던 소셜 미디어나 웹 사이트를 이용해 로그인을 할 수 있게 하는 기능이다.

클릭 한 번만으로도 로그인이 가능하고, Facebook이나 네이버 등 웹 사이트가 제공하는 기능과 API를 사용할 수 있다는 장점이 있다.

위의 사진은 인프런(강의 웹 사이트)으로, 하단에 OAuth가 적용된 것을 볼 수 있다.


OAuth를 통한 로그인 다이어그램

우선, OAuth가 어떻게 돌아가는지 부터 알아야 한다.

카카오, 네이버, 깃랩 등은 추후에 학습하며 추가적으로 구현해볼 예정이고, 구글부터 알아보자!


Google OAuth 로그인


패키지 설치

Nest.js 프로젝트를 생성하고, 필요한 패키지들을 인스톨한다.

npm install @nestjs/cli
npx nest new [프로젝트 명]
npm install --save @nestjs/passport passport passport-google-oauth20

Google Cloud 설정

아래의 주소로 접속한다.

Google Cloud Platform


  1. 새 프로젝트 생성 클릭

  2. 프로젝트 이름 정하기

  1. User Type 정하고, 앱 정보 채우고 저장 후 계속 4번 클릭

  1. 프로젝트 명 확인 후, 사용자 인증 정보 - 사용자 인증 정보 만들기 - OAuth 클라이언트 ID

  1. 유형 및 이름 설정, 승인된 자바스크립트 원본 및 리디렉션 URI 설정

  • 예시

  1. 클라이언트 ID 및 보안 비밀 번호 생성 완료


Nest.js를 통한 OAuth 구현

.env 환경 설정 파일 생성

GOOGLE_CLIENT_ID=[클라이언트 ID]
GOOGLE_SECRET=[클라이언트 보안 비밀번호]

Passport 를 사용해 google 로그인을 적용하기 위한 Strategy 를 작성

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-google-oauth20';

@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
  constructor() {
    super({
      clientID:
        '클라이언트 ID', // CLIENT_ID
      clientSecret: '클라이언트 보안 비밀번호', // CLIENT_SECRET
      callbackURL: '리디렉트 URI', // redirect_uri
      passReqToCallback: true,
      scope: ['profile'], // 가져올 정보들
    });
  }

  async validate(
    request: any,
    accessToken: string,
    refreshToken: string,
    profile,
    done: any,
  ) {
    try {
      console.log(profile);

      const jwt = 'placeholderJWT';
      const user = {
        jwt,
      };
      done(null, user);
    } catch (err) {
      console.error(err);
      done(err, false);
    }
  }
}

로그인과 관련된 Controller

import { Controller, Get, UseGuards, Res, Req } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Controller('auth')
export class AuthController {
  @Get('google')
  @UseGuards(AuthGuard('google'))
  async googleLogin(): Promise<void> {
	}

  @Get('google/callback')
  @UseGuards(AuthGuard('google'))
  async googleLoginCallback(@Req() req, @Res() res): Promise<void> {
    const jwt: string = req.user.jwt;
    if (jwt) res.redirect('http://localhost:3000/login/success/' + jwt);
    else res.redirect('http://localhost:3000/login/failure');
  }

  @Get('protected')
  @UseGuards(AuthGuard('jwt'))
  protectedResource() {
    return 'JWT is working!';
  }
}

localhost:3000/auth/google 로 접속한 결과


→ 정상적으로 로그인 페이지가 실행되는 것을 볼 수 있다!


향후 계획

  • 타입스크립트에 익숙하지 않은 탓이기도 하고, 코드를 완벽하게 이해하고 구현하지 못하고, 원리를 이해하는데 중점을 두었다.
  • 현재는 로그인 후 유저 정보를 가져오는 것까지 성공했으니, 추후에 프론트 팀과 연동 및 JWT를 이용한 유저 2차 인증을 구현해보자.
  • 구글 이외에 카카오, 깃랩, 네이버 등도 시도해보자.

참고 문헌

KSK-yun님
sinf님

profile
기억보단 기록을

2개의 댓글

comment-user-thumbnail
2023년 2월 13일

꼼꼼하게 정리를 잘했네요

답글 달기
comment-user-thumbnail
2023년 3월 11일

차근차근 잘 했네요

답글 달기