passport

박정훈·2022년 3월 7일
0

Backend

목록 보기
6/6

Express.js 어플리케이션에 간단하게 사용자 인증 기능을 구현하게 도와주는 패키지다.
유저 세션을 관리하고, 다양한 로그인 방식(구글, 카카오 등)을 추가할 수 있다.
그러니까... 쿠키와 세션을 주고받는 과정을 직접 다 구현하지 않고, passport를 통해 쉽게
사용자 인증을 할 수 있다.

passport 사용시 구현해야 할 것들

  1. Strategy
  2. Serialize
  3. deserialize

Client가 Server API에 로그인 요청을 보낸다. passport는 Strategy로 간다.
Strategy에서 DB에서 유저를 찾아보고, 유저가 존재하는지 확인한다.
유저가 존재한다면 Serialize에서 client에게 쿠키를, server에 세션을 저장한다.
로그인 성공!

유저가 다른 어떤 API를 요청한다면(server에 세션이 존재한다면) deserialize로 이동한다.
deserialize는 세션에 존재하는 req.user를 Server API에 보냄으로써 이 유저가 로그인을 한
상태라는 것을 알고 접근을 허락 해 준다.

const session = require("express-session");
const passport = require("passport");
const Strategy = require("passport-local");

//post 에서 body를 사용하기 위한 선행작업. 이 또한 하나의 미들웨어다.
// use의 위치는 중요하다. 위로 올리지 않으면 미들웨어를 거치지 않기에 body를 해석하지 못한다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// passport와 session 사용을 위한 선행작업. 미들웨어다.
app.use(
  session({
    secret: "secret",
    resave: true,
    saveUninitialized: true,
  })
);
app.use(passport.initialize());
app.use(passport.session());

// ===========================================================
  
// strategy 전략 부분. 인증 처리
passport.use(
  new Strategy(async (username, password, done) => {
    console.log(`아이디: ${username}, 패스워드 ${password}`);
    const userData = await User.findOne({ username });
    if (!userData) {
      // 아이디가 없다. 2번째 인자가 false이기 때문에 serializeUser로 가지 않는다.
      done(null, false);
    } else if (userData.password === password) {
      // 유저 정보를 done의 2번째 인자로 넘긴다. serializeUser의 user로 데이터가 간다.
      done(null, userData);
    } else {
      // 패스워드가 틀렸다
      done(null, false);
    }
  })
);

// serialize
// strategy 에서 성공했다면, userData가 첫번째 인자 user로 넘어온다.
passport.serializeUser((user, done) => {
  console.log("최초 인증됨", user);
  done(null, user); // 브라우저에게 쿠키 주고, 내부적으로 세션 저장
});
// 이미 인증이 성공한 뒤에, 추가적인 api 요청이 있을 때
passport.deserializeUser((user, done) => {
  console.log("이미 인증된 유저", user);
  done(null, user); // req.user가 갱신
});

// 세션을 미들웨어 넣어서 확인 해 보자
// 쿠키와 세션의 정보가 같다면 deserialize 를 거쳐 세션이 제대로 출력 될 것이다.
// 로그인 후 계속 새로고침 해보면 deserialize의 "이미 인증된 유저" 와 session 이 계속 출력된다.
app.use((req, res, next) => {
  console.log("세션을 알아보자 : ", req.session);
  next();
});


// 로그인 요청이 오면, 인증 처리로 이동하라. passport.use로 이동
app.post(
  "/login",
  passport.authenticate("local", {
    successRedirect: "/", // 성공시 res.redirect('/') 하라
    failureRedirect: "/login", // 실패시 res.redirect('/login') 하라
  })
);


app.get("/login", (req, res) => {
  res.send(
    `
    <form action="/login" method="POST">
      <input type="text" name="username">
      <input type="password" name="password">
      <input type="submit" value="로그인">
    </form>
    `
  );
});

app.get("/logout", (req, res) => {
  req.logout(); // 세션을 지운다.
  console.log(req.session);
  res.redirect("/");
});

로그인하고 Application 의 cookies 확인!
Network의 localhost Headers 의 Cookie 확인!

passport-local

passport는 다양한 로그인 방식을 구현하기 위해 strategy라는 인터페이스를 제공한다.
passport가 로그인 방식을 어떻게 처리할지에 대한 인터페이스를 제공한다.
passport-local은 username, password를 사용하는 로그인의 구현체다.
local로 우리만의 인증 서비스를 제공한다.

로그인 확인 미들웨어

미들웨어도 추가해 주면 좋을거 같다.

function loginRequired(req, res, next) {
  if(!req.user) {
    res.redirect('/');
    return;
  }
  next();
}
profile
그냥 개인적으로 공부한 글들에 불과

0개의 댓글