Node.js 로그인 구현하기 (passport)

2023. 11. 25. 10:47BACKEND

728x90

passport란

passport는 npm 모듈이며 로그인처리 및 session 관리를 편리하게 도와준다. passport는 독특하게 Strategy(전략)이라는 개념을 사용한다 passport-local은 로그인을 직접 구현할 때 사용하고 passport-google-oauth, passport-facebook, passport-twitter, passport-kakao, passport-naver 등등 oauth를 통해 SNS가입을 관리하는것도 지원한다.

localStrategy 구현하기

npm i passport

passport 모듈을 다운로드 받는다.

App.js - Root 파일

    const passport = require('passport');
    const passportConfig = require('./passport/index');
    passportConfig(passport);

    // express.session이 먼저 선언되어 있어야 한다.
    app.use(passport.initialize()); // passport 설정 초기화
    app.use(passport.session()); // 사용자 정보를 session에 추가한다, passport.deserializeUser() 실행

위 코드처럼 app.js에서 passport를 app.js에 붙인다.

localStrategy(일반로그인) - router 설정


    router.post('/login', (req, res, next)=>{
        passport.authenticate('local', (authError, user, info)=>{
            if( authError ){
                // 에러가 발생한 경우
                console.error(authError);
                return next(authError);
            }
            if( !user ){
                // 에러도 아니고 사용자 정보도 없는경우
                req.flash('loginError', info.message);
                return res.redirect('/');
            }
            return req.login(user, (loginError)=>{ // passport에서 req.login을 사용가능하게 해준다.
                if( loginError ){
                    console.error(loginError);
                    return next(loginError);
                }
                // 로그인에 최종적으로 성공했다면 req.user를 통해 로그인된 사용자정보를 가져올 수 있다.
                return res.redirect('/');
            });
        })(req, res, next)
    });

    /*
        localStrategy.js 에서 작성했던 done(에러, 성공, 실패) 코드가
        아래의 코드로 전달된다.
    
        passport.authenticate('local', (authError, user, info)=>{
            // code
        })(req, res, next)
    */

위에 코드는 로그인 요청이 들어왔을때의 router에서 어떻게 동작할건지에 대한 코드이다.

passport/index.js - passport Root파일

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

    module.exports = (passport)=>{
        // 최초 로그인할때
        passport.serializeUser((user, done)=>{
            done(null, user.id);
        });

        // 로그인
        passport.deserializeUser((id, done)=>{
            User.findOne({ where: { id } })
                .then((user)=>{
                    done(null, user);
                })
                .catch((error)=>{
                    console.error(error);
                    next(error);
                });
        });

        local(passport);
        kakao(passport);
    }

위에 코드는 passport 전략들을 index.js로 모아서 관리하기위한 내용이다.

passport/localStrategy.js - local에서 로그인할때 사용할 전략(Strategy)



    const LocalStrategy = require('passport-local').Strategy;
    const bcrypt = require('bcrypt');
    const { User } = require('../models/index');

    module.exports = (passport)=>{
        passport.use(new LocalStrategy({
            // usernameField와 passwordField는 패키지에서 정해진 프로퍼티 이다.
            usernameField: 'id',
            passwordField: 'password',
        }, async (id, password, done)=>{ // done(에러, 성공, 실패);
            try{
                const exUser = await User.findOne({ where: { user_id: id } });
                if( exUser ){
                    // bcrypt.compare는 비교를 해주는 패키지의 기본 메서드 이다.
                    const result = await bcrypt.compare(password, exUser.password);
                    if( result ){
                        done(null, exUser);
                    }else{
                        done(null, false, { message: '비밀번호가 일치하지 않습니다.' });
                    }
                }else{
                    done(null, false, { message: '가입되지 않은 회원입니다.' });
                }
            }catch(error){
                console.error(error);
                done(error);
            }
        }));
    };


    /*
        done(서버에러) -> try,catch에서 catch문에 잡혔다면 에러가 발생한 것이니 done()함수안에 error를 넣어준다.
        done(null, 사용자정보) -> 로그인에 성공한 경우
        done(null, false, 실패정보) -> 로그인에 실패했으니 사용자 정보는 false고 실패정보 메세지를 담는다.
    */

유의해야할 내용은 처음 사용자가 아이디,비밀번호를 입력해 passport가 실행될때는 passport.serializeUser 가 실행되고 로그인이 되어있는 상태에서는 passport.deserializeUser가 실행된다는 점이다.

 

전 회사에서는 JWT를 통한 로그인, session관리를 했었다. 이전에 내가혼자 만들때에는 passport를 통해 쿠키로 관리를 했었다 백엔드를 잘모르는 사람도 passport를 통해 편리하게 로그인관리를 할 수 있을것이라 생각한다.

'BACKEND' 카테고리의 다른 글

스프링 AOP 공부하기  (1) 2023.11.28
Node.js - sequelize ORM 알아보기  (1) 2023.11.26
Mybatis 간단 사용법 익히기  (1) 2023.11.21
JPA 학습하기 (2편)  (1) 2023.11.20
JPA 학습하기 (1편)  (3) 2023.11.19