[Node.js] 카카오 로그인&JWT

2021. 9. 17. 16:49Web_Programming/Node.js

이전에 [리액트_ts를 이용하여, 카카오 로그인 구현]에 대해 포스팅했습니다.

keeper.tistory.com

 

[React]카카오 REST API 로그인_TS

소셜 로그인 중 가장 대표적으로 사용되는 것이 카카오 로그인입니다. 개발 문서도 자세히 나와있어서, 저도 카카오 로그인을 택했습니다 다만 보안 강화를 위해서 JWT를 추가적으로 이용하였습

keeper.tistory.com

이번에는 서버 측에서 처리한 카카오 로그인 구현에 대해 작성해볼게요 :-D

 


 

카카오 로그인 구현

토큰을 이용한 로그인의 전체적인 흐름은 다음과 같습니다.

  1. 로그인 → 인가 코드 발급 client
  2. 인가 코드 → 토큰 발급(access, refresh) client
  3. access토큰을 서버로 넘겨 사용자 인증 후 DB 저장 → JWT 토큰 발급 server
  4. JWT 토큰 localStorage에 저장 후, 자동 로그인 처리 client

서버 파트는 여기서 3번의 로직을 처리하게 됩니다

 

Get Profile

access 토큰을 이용하여 카카오로부터 User 정보 받기

 

저는 프로필 정보를 받는 getProfile promise를 따로 파일에 생성해뒀습니다.

const request = require('request');

module.exports = {
  getProfile(accessToken) {
    return new Promise((resolve, reject) => {
      request( 
        {
          headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
          },
          url: 'https://kapi.kakao.com/v2/user/me',
          method: 'GET',
        },
        (error, response, body) => {
          if (!error && response.statusCode === 200) {
            resolve(body);
          }
          reject(error);
        }
      );
    });
  },

 

User 정보 받기

 

카카오 로그인을 이용한 초기 로그인의 경우,

위에서 언급한 getProfile에 프론트로부터 받은 카카오 access_token을 넘겨 User 정보를 카카오로부터 받습니다.

 

자동 로그인의 경우는 프론트에서 header로 넘긴 JWT 토큰을 통해 User 정보를 받습니다.

(JWT 인증방법은 하단에서 설명)

const express = require('express');
const kakaoAuth = require('../utils/KakaoAuth');
const router = express.Router();
router.post('/kakao', async (req, res) => {
  try{
    let userEmail = "";
    let userNickName = "";
    if (req.body.access_token) {
    //초기 로그인
      const result = await kakaoAuth.getProfile(req.body.access_token);
      const kakaoUser = JSON.parse(result).kakao_account;
      userEmail = kakaoUser.email;
      userNickName = kakaoUser.profile.nickname;
    } else {
    //자동 로그인
      const user = jwt.verify(req.headers.authorization, process.env.JWT_SECRET, {
        ignoreExpiration: true,
      });
      userEmail = user.email;
    }

  } catch (err) {
    return res.status(500).json({
      success: false,
      error: err.toString(),
    });
  }
});

 

User 정보 create or find

위에서 받은 user 식별 정보 (email)를 이용하여

 

if DB에 User정보가 있다면 → find

elsecreate 하여 계정을 생성해줍니다.

    const [user, created] = await User.findOrCreate({
      where: { email: userEmail },
      defaults: {
        socialType: 'kakao',
        nickName: userNickName,
        kakaoToken: req.body.access_token
      },
      attributes: ['id', 'nickName'],
    });

    let responseData = {
      success: true,
      user,
    };

 

JWT 토큰 생성

초기 로그인의 경우 JWT 토큰을 프론트로 넘겨줘야 하기 때문에,

jwt.sign을 통해 JWT 토큰을 발급하여 res.json으로 넘겨줍니다.

    if (req.body.access_token) {
      const token = jwt.sign({
        id: user.id,
        email: userEmail,
      }, process.env.JWT_SECRET, {
        issuer: 'bbangsoon',
      });
      responseData.jwt = token;
    }

    return res.status(created? 201: 200).json(responseData);

이렇게 jwt토큰과 user 정보를 넘기면

서버에서의 카카오 로그인 구현 끝입니다

 

+ 쿠키 기반 인증 로직을 사용하는 경우, json이 아닌 cookie에 설정해주면 됩니다.

 

 

/auth 전체 코드

const express = require('express');
const jwt = require('jsonwebtoken');
const { User } = require('../models');
const kakaoAuth = require('../utils/KakaoAuth');

const router = express.Router();

router.post('/kakao', async (req, res) => {
  try{
    let userEmail = "";
    let userNickName = "";
    if (req.body.access_token) {
    //초기 로그인
      const result = await kakaoAuth.getProfile(req.body.access_token);
      const kakaoUser = JSON.parse(result).kakao_account;
      userEmail = kakaoUser.email;
      userNickName = kakaoUser.profile.nickname;
    } else {
    //자동 로그인
      const user = jwt.verify(req.headers.authorization, process.env.JWT_SECRET, {
        ignoreExpiration: true,
      });
      userEmail = user.email;
    }

    const [user, created] = await User.findOrCreate({
      where: { email: userEmail },
      defaults: {
        socialType: 'kakao',
        nickName: userNickName,
        kakaoToken: req.body.access_token
      },
      attributes: ['id', 'nickName'],
    });

    let responseData = {
      success: true,
      user,
    };

    if (req.body.access_token) {
      const token = jwt.sign({
        id: user.id,
        email: userEmail,
      }, process.env.JWT_SECRET, {
        issuer: 'bbangsoon',
      });
      responseData.jwt = token;
    }

    return res.status(created? 201: 200).json(responseData);
  } catch (err) {
    return res.status(500).json({
      success: false,
      error: err.toString(),
    });
  }
});

 

 

JWT 인증 방법

패키지 설치

npm i jsonwebtoken

.env 파일에 JWT_SCERET으로 설정하고자 하는 secret key 값을 지정합니다.

 

jwt.sign

: 계정 생성

first_param : 계정 정보

second_param : 설정한 secret key

const token = jwt.sign({
        id: user.id,
        email: userEmail,
      }, process.env.JWT_SECRET, {
        issuer: 'bbangsoon',
      });

jwt.verify

: 사용자 인증

first_param : JWT 토큰

second_param : 설정한 secret key

const user = jwt.verify(access_token, process.env.JWT_SECRET, {
        ignoreExpiration: true,
      });
반응형

'Web_Programming > Node.js' 카테고리의 다른 글

[Node.js] NCP SENS 문자 발송 API  (4) 2021.05.29