[NODE] Passport 로 카카오 로그인 구현

서수·2022년 12월 12일
1

Passport

목록 보기
1/1
post-thumbnail

Passport로 카카오 로그인 구현하기

Passport 미들웨어 모듈을 사용하여 카카오 로그인을 구현해 보았습니다. 파일 구조는 router의 분리와 Passport 폴더 안 index.js 및 kakaoStrategy, localstrategy 등 여러 파일로 나눠줘야 하지만 이해를 쉽게 하기 위해서 한 파일 내에 구성하였습니다. 프론트는 pug 파일을 사용하였습니다. DB는 몽구스를 사용하였습니다.

kakao Development 설정


자신이 진행할 앱 이름과 사업자 명 등 적어줍니다.


왼쪽 플랫폼 란에 사이트 도메인을 적어줍니다. 저는 localhost 에서 돌려볼 것이기 때문에 localhost:3000 을 적었지만 나중에 배포를 하고 나서는 바꿔줘야 합니다.

도메인은 콜백을 받을 도메인이며 작성을 똑바로 해줘야 서버로부터 카카오 계정을 넘겨받을 수 있습니다.

카카오 로그인을 활성화 해주고 Redirect URI 를 적어줍니다. 카카오 서버에서 어느 주소로 REST API GET 요청을 보낼지 적어주는 것 입니다.


다음은 동의항목을 적어줍니다. 동의항목을 설정하는 만큼 DB에 저장되는 항목을 늘려줘야 합니다.

다음은 앱 키들입니다. 코드를 짜면서 필요한 정보들이니 유출되지 않게 dotenv 파일에 넣어줍니다.

카카오 로그인 전략 구현

카카오 로그인은 인증과정을 카카오에 맡기는 것입니다.
사용자는 번거롭게 회원가입을 할 필요가 없고, 서비스 제공자는 로그인 과정을 검증된 SNS에 맡길수 있어 편합니다. 그리고 딱히 번거로운 회원가입 절차도 없습니다.

필요한 모듈들

필요한 모듈들을 아래 명령어를 통하여 깔아줍니다.

$ npm install passport passport-kakao
$ npm install express
$ npm install dotenv
$ npm install mongoose
$ npm install express-session
$ npm install pug
$ npm install body-parser
$ npm install cookie-parser

파일 구조

파일 구조는 이렇게 만들어 줬습니다. 위에 설명했듯이 원래는 세부적으로 파일이 나눠져 있지만
좀 더 간편한 구현과 설명을 위해 하나에 몰아 넣어주었습니다.

프론트 코드

src/views/home.pug

html(lang="en")
    head
        meta(charset="UTF-8")
        meta(http-equiv="X-UA-Compatible", content="IE=edge")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        title Social Login  
        link(rel="stylesheet", href="https://unpkg.com/mvp.css")
        link(rel="stylesheet", href="/public/style/stylesheet.css")
        link(rel="icon", href="/favicon.ico", type="imgae/x-icon")
        link(rel="shortcut icon", href="/favicon.ico" type="image/s-icon")
    
    body
        header 
            h3 소셜로그인
        main 
            div#SocialLogin
                h3 카카오로그인 예제
                form
                    a#kakao(type="button")
                        img(src='/public/static/kakaobutton.png', width="80")

script(src="/public/js/home.js")

src/public/js/home.js

//div#SocialLogin 의 Id를 갖고오는것
const SocialLogin = document.getElementById("SocialLogin");
//div#SocialLogin 안에 폼을 갖고 오는것.
const SocialLoginForm = document.querySelector("form");
//div#SocialLogin 안에 있는 폼 안의 a 값을 가져온 것.
const kakaoButton = SocialLoginForm.querySelector("#kakao");
// 카카오버튼에 Click 이라는 이벤트가 발생하면 LoginKakao 함수 실행
kakaoButton.addEventListener("click", LoginKakao)
//함수는 localhost:3000/auth/kakao 로 이동시켜주는 함수
function LoginKakao(){
    window.location.href = 'http://localhost:3000/auth/kakao'
}

보이는 화면

간단하게 카카오톡 아이콘만 보여지게 하고, 저 카카오 버튼을 누르면 카카오 로그인 창으로 넘어가게끔 구성해 주었습니다.

백엔드 코드

server.js

const express = require('express');
const app = express();
const session = require('express-session')
const bodyParser = require('body-parser')
const cookieParser = require("cookie-parser");
const routes = require('../routes');
const connect = require("../schema")
connect();
require("dotenv").config();

app.use(
    session({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: false,
    cookie:{secure:true}
    }),
);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());

app.set("view engine", "pug");
app.set("views", __dirname + "/views");
app.use("/public", express.static(__dirname + "/public"));
app.use("/", routes)

app.get("/", (_, res) => res.render("home"));

app.listen(3000, () => {
    console.log("3000 open!")
})

localhost:3000으로 접속하면 보이는 화면부분이 보이게끔 프론트 파일들을 불러와 줍니다.
기본적으로 Passport는 Session을 사용하기 때문에 session 미들웨어도 넣어주었습니다.

schema/users.js

const mongoose = require('mongoose');

const { Schema } = mongoose;
const KakaoSchema = new Schema({
  userId: { 
    type: String,
    required: true,
  },
  nickname: { 
    type: String,
    required: true,
  },
  password: {
    type: String
  },
  provider: {
    type: String
  },
  refresh_token: {
    type: String,
  },  
},
{
    timestamps:true
});

module.exports = mongoose.model('Kakao', KakaoSchema);

다음은 DB 구성입니다. 저는 동의항목에 닉네임만 넣어줬기 때문에 고유한 아이디 값을 넣을 userId 와 카카오 닉네임을 넣을 nickname 항목, 그리고 어떤 SNS에서 가입했는지 구별을 해주기 위해서 provider 항목을 넣었습니다. 또한 소셜로그인에는 refreshToken 이 필요하므로 refreshToken을 저장 해줄수 있는 공간인 refresh_token 도 넣었습니다.

routes/index.js

const express = require('express');
const router = express.Router();

const authRouter = require("./auth.router");

router.use("/auth", authRouter);

module.exports = router;

다음은 routes 의 index.js 입니다. auth.router 을 불러와 router 설정을 해주었습니다.

routes/auth.router.js

const express = require('express')
const router = express.Router();
const passport = require('passport');
const KakaoStrategy = require('passport-kakao').Strategy;
require("dotenv").config();

const Kakao = require('../schema/users')

passport.use(
    'kakao',
    new KakaoStrategy({
        clientID: process.env.KAKAO_RESTAPI_KEY,
        callbackURL: '/auth/kakao/callback',
        clientSecret: process.env.KAKAO_SECRET_KEY
    },
    async(accessToken, refreshToken, profile, done) => {        
        console.log('kakao profile', profile);
        console.log(accessToken)
        console.log(refreshToken)
        try{
            const exUser = await Kakao.findOne({userId: profile.id, provider:'kakao'});
            if(exUser){
                done(null, exUser)
            } else {
                const newUser = await Kakao.create({                    
                    nickname: profile.displayName,
                    userId: profile.id,
                    provider:'kakao',
                    refresh_token: refreshToken
                });
                done(null, newUser)
            }
        }catch(error){
            console.log(error)
        }
    }
    )
)

router.get('/kakao',passport.authenticate('kakao'));

router.get('/kakao/callback',
    passport.authenticate('kakao'), (req,res)=>{
        res.redirect('/')
    }       
)

passport.serializeUser(function (user, done) {
    done(null, user);
    });
    passport.deserializeUser(function (user, done) {
    done(null, user);
    });

module.exports = router;

다음은 카카오 로그인 Strategy가 다 들어있는 auth.router.js 파일입니다.
기본적으로 passport.use 뒤에 kakao 부분이 있어야 kakao를 통해 인증을 시작합니다.
kakaoStrategy 부분엔 clientID, callbackURL, clientSecret 을 설정해줘야 합니다. clientID에는 앱 키의 REST API 키를, callbackURL에는 카카오 로그인의 Redirect URI를, clientSecret 에는 카카오 Development 의 카카오 로그인 > 보안 란에 코드를 넣어주시면 됩니다.
아래 부분을 보시면 acessToken, refreshToken, profile, done 이 있는데
회원가입이 완성 되면 acessToken과 refreshToken, 그리고 유저 정보가 담겨있는 profile이 넘어오며 완성이 되면 done 함수의 내용으로 넘어가게 됩니다. 아래 console.log 를 통하여 토큰들과 유저 정보들이 잘 넘어오는지 확인해 보겠습니다. 그 아래 로직은 이미 회원가입이 되어 있으면 DB에서 찾아와 done 함수로 넘어가게 되며 만약에 없으면 DB에 create 해주는 로직입니다.

그 아래 Router 부분은 /auth/kakao 로 들어가게 되면 kakao의 passport가 실행이 되어
로그인 창으로 넘어가게 해주는 것이고, 아래는 회원가입 완료시 callback을 받을 URI 을 설정해 준 대로 경로를 짜주면 되겠습니다. 그리고 callback 이 되면 localhost:3000/ 으로 넘어가게끔 redirect 해준 모습입니다.

그 아래 코드는 Session 인증에 관한 부분입니다.

실행 결과

이렇게 하고 서버를 실행해보면 카카오 버튼을 눌렀을 때

이렇게 로그인 창이 뜹니다.

정보를 입력하고 로그인을 하면 VScode 에서는

이렇게 유저정보가 잘 넘어오는 것을 볼 수 있으며 아래에는 AccessToken 그리고 RefreshToken 도 잘 넘어오는 것을 볼 수가 있습니다.

그리고 DB를 보면 DB에도 이렇게 잘 저장되는 모습을 볼 수가 있습니다.

profile
패션디자인과 출신 비전공자가 개발자로 성장하려 만든 노트

0개의 댓글