inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

Slack 클론 코딩[백엔드 with NestJS + TypeORM]

카카오 로그인 serializer 구현

569

이민석

작성한 질문수 6

0

안녕하세요 제로초님.

passport-kakao를 이용해서 kakao 로그인을 구현해보고 있습니다.

로그인과 회원가입 까지는 잘 되는데, serializer을 통해서 cookie가 저장되지 않습니다.

 

kakako.strategy.ts

import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-kakao';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as _ from 'lodash';
import { AuthService } from './auth.service';
import { Platform } from 'src/entities/common/Platforms';

@Injectable()
export class KakaoStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly configService: ConfigService,
    private authService: AuthService,
  ) {
    super({
      clientID: configService.get<string>('KAKAO_REST_API_KEY'),
      clientSecret: configService.get<string>('KAKAO_CLIENT_SECRET'),
      callbackURL: configService.get<string>('KAKAO_REDIRECT_URI'),
    });
  }

  async validate(accessToken, refreshToken, profile, done) {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const {
      _json: {
        id,
        properties: { nickname, profile_image: profileImage },
        kakao_account: { email },
      },
    } = profile;

    const user = await this.authService.findOrCreateUser(
      email,
      nickname,
      Platform.KAKAO,
    );
    return done(null, user);
  }
}

 

아래에 있는 kakao-auth.guard.ts와 kakao.serializer.ts는 로컬 로그인과 다른 점이 없을 것 같아서 그대로 썼습니다.

 

kakao-auth.guard.ts

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

@Injectable()
export class KakaoAuthGuard extends AuthGuard('kakao') {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const can = await super.canActivate(context);
    if (can) {
      const request = context.switchToHttp().getRequest();
      await super.logIn(request);
    }
    return true;
  }
}

 

kakao.serializer.ts

import { Injectable } from '@nestjs/common';
import { PassportSerializer } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { AuthService } from './auth.service';
import { Users } from 'src/entities/Users';

@Injectable()
export class KakaoSerializer extends PassportSerializer {
  constructor(
    private readonly authService: AuthService,
    @InjectRepository(Users) private usersRepository: Repository<Users>,
  ) {
    super();
  }

  serializeUser(user: Users, done: CallableFunction) {
    done(null, user.id);
  }

  async deserializeUser(userId: string, done: CallableFunction) {
    return await this.usersRepository
      .findOneOrFail({
        where: { id: +userId },
        select: ['id', 'email', 'nickname'],
      })
      .then((user) => {
        done(null, user);
      })
      .catch((error) => done(error));
  }
}
  1. 이처럼 작성하면, 로그인 시 세션에 쿠키가 저장되어야 하는게 아닌가요?

  2. 사실 강의에서 설명해주신 내용중 이해가 잘 가지 않는 부분이 있습니다.


    localStrategy에서 done(null, user) -> local-auth.guard.ts에서 super.logIn(request) -> local serializer 에서 serializeUser() 을 호출한다고 말씀하셨는데,
    세 가지 파일에서 LocalStrategy, LocalAuthGuard, LocalSerializer을 서로 명시적으로 연결해준적이 없음에도 불구하고 어떻게 서로 잘 알아서 호출되는지 궁금합니다.
    그냥 앞에 모두 Local이 붙어서, 잘 찾아서 호출되는 건가요?

node.js express nestjs typeorm

답변 1

0

제로초(조현영)

일단 카카오시리얼라이저를 따로 두실 필요 없고 로컬 시리얼라이저로 공용으로 쓸 수 있습니다. 코드로는 컨트롤러랑 모듈쪽도 같이 봐야할 것 같습니다.

@nestjs/passport 내부적으로 처리해주는 것이라 명시적인 연결 관계가 없습니다. express+passport에서도 이 때문에 헷갈리는 부분입니다.

0

이민석

authModule은 그냥 provider에 다 집어넣었습니다.

authController를 따로 만들지 않았고, 그냥 userController에 로컬로그인 + 카카오로그인 모두 처리했습니다

user.controller.ts

import {
  Body,
  Controller,
  Get,
  Post,
  Req,
  Res,
  UseGuards,
} from '@nestjs/common';
import { JoinRequestDto } from 'src/dto/join.request.dto';
import { UsersService } from './users.service';
import { User } from 'src/decorators/user.decorator';
import { LocalAuthGuard } from 'src/auth/local-auth.guard';
import { AuthGuard } from '@nestjs/passport';
import { KakaoAuthGuard } from 'src/auth/kakao-auth.guard';

@Controller('api/users')
export class UsersController {
  constructor(private userService: UsersService) {}
  @Get()
  getUsers(@User() user) {
    return user;
  }

  @Post()
  async postUsers(@Body() body: JoinRequestDto) {
    await this.userService.postUsers(body.email, body.password, body.nickname);
  }

  @Post('login')
  @UseGuards(LocalAuthGuard)
  logIn(@Req() req) {
    return req.user;
  }

  @Get('login/kakao')
  @UseGuards(KakaoAuthGuard)
  kakaoLogIn() {
    return;
  }

  @Get('login/kakao/callback')
  @UseGuards(KakaoAuthGuard)
  kakaoLogInRedirect(@Req() req) {
    return req.user;
  }

  @Post('logout')
  logOut(@Req() req, @Res() res) {
    req.logOut();
    res.clearCookie('connect.sid', { httpOnly: true });
    res.send('ok');
  }
}

로컬 시리얼라이저를 공용으로 사용하려면 어떻게 해야하나요?

0

제로초(조현영)

카카오 시리얼라이저를 제거하고 로컬 시리얼라이저만 넣으면 됩니다. 로컬 시리얼라이저에서 로컬이라는 이름은 아무 역할도 하지 않습니다. 그냥 login 후에 req.user를 생성하는 시리얼라이저일 뿐입니다.

serializeUser랑 deserializeUser 안에 콘솔로그도 찍어보세요.

강의자료는 어디서 다운받나요?

0

114

4

질문 있습니다.

0

298

3

(강의 5:42 질문) providers를 통한 여러 개의 인스턴스 생성 & exports 통한 싱글톤 생성

0

154

2

코드 편집기 확장 프로그램

0

209

2

(질문)비밀 저장소에 접근하기 위한 인증 정보는 로컬 .env에 저장하는지?

0

143

2

(질문)외부 저장소를 통한 환경변수 불러오기 비동기 질문

0

168

3

로그인을 해도 LoggedInGuard쪽에서 false값이 나옵니다.

0

152

2

로그인방법이 고민됩니다.

0

190

2

yarn seed 명령어 실행 시 데이터 삽입 안됨

0

297

4

yarn run db:create 시에 발생하는 데코레이터 오류

0

242

2

npm run db:create 시에 발생하는 decorating 오류

0

232

2

RxJS 디버깅 질문 있습니다.

0

189

3

CacheManager에 대해 질문 있습니다.

0

174

2

로깅은 어떻게 하는게 효율적일까요?

0

224

1

CORS 질문 있습니다.

0

418

2

쿠키 옵션에 대해서 질문 있습니다.

0

184

2

로그아웃 요청이 403 forbidden 에러가 나는데 왜그런걸까요??

0

449

1

401 unauthorized문제

0

288

1

가드의 장점에 대해서 질문이 있습니다.

0

225

1

로그 관리에 대해 질문 있습니다.

0

252

2

CORS 에러 질문 있습니다.

0

319

2

배포 환경 DB 연결 질문 있습니다.

0

411

2

socket io 미 연결 문제 (nest & flutter)

1

1154

3

no elements in sequence 에러 관해서 질문이 있습니다.

0

454

1