[노드, 리액트 기초 | node.js] #10. auth 기능 구현하기

ppmyor·2022년 7월 10일
0

노드, 리액트 기초

목록 보기
10/26
post-thumbnail

😵‍💫 Auth가 뭔가요?

사이트에는 모든 사용자가 이용이 가능한 페이지, 로그인 된 사용자만 이용 가능한 페이지, 로그인 된 사용자 중에 특정 사용자만 이용이 가능한 페이지, admin만 접근이 가능한 페이지 등 여러가지의 페이지가 혼재되어있다. admin에 일반 사용자가 접근하거나, 특정 사용자만 이용 가능한 페이지에 guest 유저가 접근하는 불상사를 막기 위해 즉, 해당 페이지에 유저가 접근이 가능한지를 판별하기 위해 auth 기능을 사용한다.

해당 기능의 원리는 간단하다. client에서 토큰을 쿠키에 Server에서는 토큰을 DB에 넣어줬었는데, 페이지가 이동될 때 마다 token을 계속 비교하면서 auth를 체크한다.
우선, client에서 token이 담겨져있는 cookie를 server에 전달한다. 쿠키에는 encode된 토큰이 담겨있는 상태인데, 해당 토큰을 decode하면 유저 아이디가 나오게 된다. 조금 더 상세하게 말하자면 앞에서 user._id + "secretToken" = token으로 생성했는데 "secretToken"을 넣으면 user._id가 나오게 되므로 유저 아이디를 알 수 있게된다.

유저 아이디를 추출하게 되면 유저 DB에서 유저 아이디를 검색해 토큰의 유무를 통해 auth를 거를 수 있게 된다.

🔑 token decode

  1. auth 라우터 생성
const { auth } = require("./middleware/auth");
app.get("/api/users/auth", auth, (req, res) => {});

auth 라우터를 생성하고, argument에 auth라는 미들 웨어 추가한다.
미들웨어는 endpoint에 req를 받은 다음 callback function을 호출 하기전에 중간에서 무언가를 해주는 역할이다.

  1. user Model에 findByToken 메소드 생성
userSchema.statics.findByToken = function (token, cb) {
  let user = this;

  jwt.verify(token, "secretToken", function (err, decoded) {
    user.findOne({ _id: decoded, token: token }, function (err, user) {
      if (err) return cb(err);
      cb(null, user);
    });
  });
};

verify를 이용해 토큰을 decode한다. 유저 아이디를 이용해서 유저를 찾은 다음 클라이언트에서 가져온 token과 DB에 보관된 token이 일치하는지 확인한다. 에러가 뜬다면 callback으로 에러 내용을 넘겨주고 아니라면 true를 넘겨준다.

  1. middleware/auth.js 파일 생성
const { User } = require("../models/User");

let auth = (req, res, next) => {
  let token = req.cookies.x_auth;

  User.findByToken(token, (err, user) => {
    if (err) throw err;
    if (!user) return res.json({ isAuth: false, error: true });

    req.token = token;
    req.user = user;
    next();
  });
};

module.exports = { auth };

인증 처리들을 할 auth.js 파일을 생성한다.
유저가 없거나 에러인 경우에는 isAuth에 false를 할당한 뒤 에러를 띄워주고, 유저가 있다면 req.token에 token을 넣고 req.user에 user 정보를 넣어준다. 이렇게 하는 이유는 토큰과 유저를 req에 넣어주어서 req.user를 하면 user 정보를 req.token을 하면 token 정보를 가져올 수 있도록 하기 위해서다. next()를 호출하는 이유는 미들웨어이기 때문에 그 다음으로 넘겨주기 위해서 호출한다.

  1. index.js 파일의 auth 라우터 내용 수정
app.get("/api/users/auth", auth, (req, res) => {
  res.status(200).json({
    _id: req.user._id,
    isAdmin: req.user.role === 0 ? false : true,
    isAuth: true,
    email: req.user.email,
    name: req.user.name,
    lastname: req.user.lastname,
    role: req.user.role,
    image: req.user.image,
  });
});

index 까지 미들웨어를 통과해 왔다는 이야기는 Authentication이 true라는 이야기이므로 user 필드의 내용들을 넘겨준다.😵‍💫

➕ 참고

따라하며 배우는 노드, 리액트 시리즈 - 기본 강의 를 공부하며 작성한 글입니다.

profile
유영하는 개발자

0개의 댓글