글 작성자: 망고좋아
반응형

🎯 Passport.js와 로그인

📝 Passport.js란?

  • Express.js 애플리케이션에 간단하게 사용자 인증 기능을 구현하게 도와주는 패키지이다.
  • 유저 세션 관리 및 다양한 로그인 방식 추가할 수 있다.

 

📝 passport-local

  • passport는 다양한 로그인 방식을 구현하기 위해 strategy라는 인터페이스를 제공한다.
  • strategy는 passport가 로그인 방식을 어떻게 처리할지에 대한 인터페이스를 미리 설계한 거다.
  • strategy 인터페이스에 맞게 설계된 다양한 구현체들이 있다. (facebook, google,...) 자연스럽게 login flow를 구현할 수 있게 도와준다.
  • passport-local은 username, password를 사용하는 로그인의 구현체이다.

 

📝 로그인 기능 구현하기

📕 기본 로직

  1. 로그인 화면 구성하기
  2. passport-local strategy로 로그인 구현하기
  3. passport.js 설정하기
  4. passport로 요청 처리하기

 

📕 로그인 화면 구성

...
form(action="/auth" method="post" onsubmit="return check()")
    table
        tbody
            tr
                td 이메일
                td: input(type="text" name="email")
            tr
                td 이메일
                td: input(type="password" name="password")
            tr
                td(colspan="2")
                td: input(type="submit" name="로그인")
...
...
script.
    function check() {
      const email = document.querySelector('name=["email"]').value;
      if (!email) {
        alert("이메일을 입력 해 주세요");
        return false;
      }

      const password = document.querySelector('name=["password"]').value;
      if (!email) {
        alert("비밀번호를 입력 해 주세요");
        return false;
      }

      return true;
    }

 

📕 passport-local strategy로 로그인 구현

🛠 /passport/strategies/local.js

const config = {
  usernameField: "email",
  passwordField: "password",
};
// 아이디 패스워드 필드 설정 필수!

const local = new LocalStrategy(config, async (email, password, done) => {
  try {
    const user = await User.findOne({ email });
    if (!user) {
      throw new Error("회원을 찾을 수 없습니다.");
    }
    if (user.password !== password) { // 평문인 password가 아닌 hash값을 사용해야 된다.
      throw new Error("비밀번호가 일치하지 않습니다.");
    }

    // 세션에 저장되는 유저 정보의 최소화
    done(null, {
      shortId: user.shortId,
      email: user.email,
      name: user.name,
    });
  } catch (err) {
    done(err, null);
  }
});
  • 이메일, 비밀번호, 완료 처리하는 콜백 함수로 구성
  • config값과 Authenticate를 사용한다.
  • strategy 안에서 로그인 처리가 되어야 한다.
  • 로그인 처리 후 어떤 데이터를 보낼지 결정하면 된다.

 

📕 Passport.js 설정하기

🛠 /passport/index.js

const local = require('./strategies/local');
passport.use(local);
  • 작성 한 strategy를 passport.use를 이용해 사용하도록 선언해야 한다.
  • passport.use를 이용해 strategy를 사용하도록 선언한 후 passport.authenticate를 사용해 해당 strategy를 이용해 요청을 처리할 수 있다.

 

📕 Passport.js로 post 요청 처리하기

// --- routes/auth.js ---
// router.post('/', passport.authenticate('local'), (req, res, next) => { res.redirect('/'); });
router.post('/', passport.authenticate('local');

// --- app.js ---
const session = require('express-session');

app.use(session({
    secret: 'secret',
    resave: false,
    saveUninitialized: true
}));

app.use(passport.initialize());
app.use(passport.session());
app.use('/auth', authRouter);
  • passport.authenticate 함수를 http 라우팅에 연결하면 passport가 자동으로 해당하는 strategy를 사용하는 request handler를 자동 생성해준다.
  • express-session과 passport.session()을 사용하면 passport가 로그인 시 유저 정보를 세션에 저장하고 가져오는 동작을 자동으로 수행해 준다.

 

📕 session 유저 활용하기

passport.serializeUser((user, callback) => {
    callback(null, user);
});

passport.deserializeUser((obj, callback) => {
    callback(null, obj);
});
  • session을 이용해 user를 사용할 때에는 serializeUser와 deserializeUser를 설정해 주어야 한다. → 세션에 user 정보를 변환하여 저장하고 가져오는 기능을 제공해 준다.
    • ex) 회원 id만 세션에 저장하고, 사용 시 회원정보를 디비에서 찾아서 사용
    • 세션 사용 시 위 두 함수를 작성하지 않으면 passport 로그인이 동작하지 않는다.

 

📕 serializeUser/deserializeUser

  • passport는 세션에 최소한의 인증 정보만 저장한다. 로그인 한 뒤 세션에 데이터를 저장할 때 어떤 정보를 저장할지를 결정하는 함수가 serizliseUser이다.
  • 반대로 세션에 저장한 데이터로 로그인한 유저 정보를 복구하는데 이걸 결정하는 함수가 deserializeUser다.

 

📝 로그아웃

router.get('/logout', ... {
    req.logout();
    res.redirect('/');
});
  • passport는 req.logout 함수를 통해 세션의 로그인 정보를 삭제하여, 로그아웃 기능을 구현할 수 있다.

 

📝 로그인 확인 미들웨어

function loginRequired(req, res, next) {
    // 미 로그인
    if (!req.user) {
        res.redirect('/');
        return;
    }
    next();
}

// ----- app.js -----
app.use('/posts', loginRequired, postsRouter); // 로그인되어 있어야지만 post 할 수 있도록 설정
  • 로그인을 필수로 설정하고 싶을 경우, 미들웨어를 사용하여 체크할 수 있다.
반응형