node.js 에서 passport로 카카오 로그인 구현하기

수영·2023년 1월 24일
0

2023 겨울방학

목록 보기
4/7

passport 모듈 설치하기

먼저 터미널에 npm i passport passport-local passport-kakao bcrypt 를 입력해 4개의 모듈을 설치해줍니다. (docker alpine 사용시 bcrypt 모듈을 사용 할 수 없기에 bcryptjs 또는 다른 해결책 방법을 사용해야한다.)

모듈을 설치했으니 app.js에서 모듈을 선언해주어야합니다.

var createError = require('http-errors');
var sequelize = require('./models').sequelize;
var express = require('express');
const session = require('express-session');
const passport = require('passport'); //추가
const passportConfig = require('./passport'); //추가
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
require('dotenv').config();


var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
const authRouter = require('./routes/auth'); //추가 (뒤에서 사용할예정)


var app = express();
sequelize.sync();
passportConfig(passport);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: process.env.COOKIE_SECRET,
  cookie: {
    httpOnly: true,
    secure: false,
  },
}));
app.use(passport.initialize()); //추가
app.use(passport.session()); //추가 (req.session 객체는 express-session에서 생성하는 것이므로 passport 미들웨어는 express-session 미들웨어보다 뒤에 연결해야 합니다.)
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/auth', authRouter); //추가 (뒤에서 사용할예정)



// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});


module.exports = app;

로그인 구현하기

먼저 새로 passport 파일을 생성한 후 index.js, kakaoStrategy.js 파일을 생성합니다.

passport/index.js

const kakao = require('./kakaoStrategy');
const {User} =require('../models');

module.exports = (passport) => {
    passport.serializeUser((user, done) =>{ //req.session 객체에 어떤 데이터를 저장할지 선택. 매개변수로 user를 받아서 done 함수에 두번째 인자로 user.id 를 넘기고 있다.(=세션에 사용자 id저장) done함수의 첫번째 인자는 에러 발생시 사용
        done(null, user.id);
    });

    passport.deserializeUser((id,done) => { // 매요청시 실행된다. passport.session() 미들웨어가 이 메서드를 호출한다. serializeUser에서 세션에 저장했던 id를 받아 데이터베이스에서 사용자 정보를 조회한다. 조회한 정보를 req.user에 저장하므로 앞으로 req.user를 통해 로그인한 사용자의 정보를 가져올 수 있다.
        User.findOne({
            where: {id}})
            .then(user=> done(null, user))
            .catch(err => done(err));
    });

    kakao(passport);
}

passport/kakaoStrategy

const KakaoStrategy = require('passport-kakao').Strategy;

const {User} = require('../models'); 

module.exports = (passport) => {
    passport.use(new KakaoStrategy({
        clientID:process.env.KAKAO_ID, //kakao에서 발급해주는 id, .env 파일 생성후 KAKAO_ID:카카오에서 발급해준 api 를 추가해주면 된다.
        callbackURL:'/auth/kakao/callback', //인증결과를 받는 라우터이다.
    }, async (accessToken, refreshToken, profile, done)=> {
        try {
            const exUser = await User.findOne({  //가입이력 확인
                where: {
                    snsId: profile.id,
                    provider: 'kakao'
                }});
            if (exUser) {
                done(null, exUser);
            } else {
                const newUser = await User.create({ //새 유저 생성
                    email: profile._json?.kakao_account_email,//nullish라 판단하면 에러가 아닌 undefined 출력
                    nick_name: profile.displayName,
                    snsId: profile.id,
                    rank:"common",
                    provider: 'kakao',
                });
                done(null, newUser);
            }
        }catch (error) {
            console.error(error);
            done(error);
        }
    }));

};

카카오 로그인 라우터 즉 어떤 라우터로 요청을 주고받는지 설정할 차례이다.

routes 폴더안에 auth.js파일을 생성하자

const express = require('express');
const passport = require('passport');
const bcrypt = require('bcryptjs'); //현재 docker alpine으로 서버를 구동중이라 bcrypt대신 bcryptjs모듈을 사용한다.
const { isLoggedIn, isNotLoggedIn } = require('./middlewares');
const { User } = require('../models');

const router = express.Router();
/*
router.get('/logout', isLoggedIn, (req,res) =>  // passport 버전이 업글되면서 문법이 바뀌었다.
    req.logout(function(err) {
        req.session.destroy();
        if (err) { return next(err); }
        res.redirect('/');
    })); // 뒤에 로그아웃 구현
*/
router.get('/kakao', passport.authenticate('kakao')); // get /auth/kakao 로 접근하면 카카오 로그인 창으로 연결된다. 
router.get('/kakao/callback',passport.authenticate('kakao',{ // 로그인에대한 결과를 GET /auth/kakao/callback 로 받는다.
    failureRedirect: '/',
    }),(req,res)=> {
    res.redirect('/');
});
module.exports = router;

이렇게하면 카카오 로그인구현은 끝이났다.

카카오로그인 실습을 위해 카카오 플렛폼 만들기접속 후 애플리케이션 추가하기버튼을 누른다.
앱 이름과 사업자명을 설정하면 된다.

아까 만들어놓은 .env파일에 KAKAO_ID:REST API키를 입력한다.
앱설정에서 플랫폼으로 들어가서 web플렛폼을 등록하고 아래 Redirect URL을 등록한다.

Client Secret 을 사용하는 경우 제품설정> 카카오 로그인 > 보안 에서 on 으로 설정을 하고 코드에 해당하는 부분을 .env에 넣고 사용하면 된다.

위 설정을 한 후 서버를 실행시켜보면 카카오 로그인이 되는 것을 볼 수 있다.

0개의 댓글