오늘은 Auth(Authentication)기능을 만들어 본다.
이게 왜 필요하냐? 사이트 내에서 로그인을 해야만 이용 가능한 정보와 그렇지 않은 정보가 있는데 이를 체크하기 위해서이다.
저번에 token을 만들었는데 이 토큰은 클라이언트쪽에서는 쿠키에 저장이 되고, 서버쪽에는 DB에 저장이 되어 있다. 이를 계속 체크하면서, 이 사용자가 정보에 접근이 가능한지 아닌지를 확인하는 것이다.
토큰을 만들 때 let token = jwt.sign(user._id.toHexString(), 'secretToken');
과 같이 만들었으니 서버쪽에서는 이 secretToken으로부터 유저 아이디를 유추하고 확인하게 된다.
오늘부터는 endpoint에 /api/users/
를 넣어주기로 했다. expressJS에서 처리를 할 때 Router를 사용할 건데 관련된 것들을 한데 정리해서 묶어두기 위해서임. 전체를 다 index.js에 두면 파일이 너무 길어지므로 추후에 분류해줄 것이다.
app.get("/api/users/auth", auth, (req, res) => {
...
})
중간에 적힌 auth는 우리가 middleware로서 이용할 것이다.
최상위루트에 middleware폴더를 만들고 여기에 auth.js를 작성하자
auth.js
let auth = (req, res, next) => {
// 인증처리를 하는 곳
};
module.exports = { auth };
그리고 index에서는 const { auth } = require("./middleware/auth");
로 import처리해주기
auth에서 해야할 것이 몇 가지 있는데
1. 클라이언트 쿠키에서 토큰 가져오기
2. 토큰을 복호화해서 유저 찾기
3. 유저가 있으면 인증ㅇㅋ
4. 유저가 없으면 인증ㄴㄴ
토큰을 가져오기 위해서 let token = req.cookies.x_auth;
를 작성했다. x_auth는 저번에 쿠키 만들 때 지정해 준 것임.
이제 토큰을 복호화해ㅐ서 유저를 찾아야 하기 때문에 const { User } = require(...)
로 유저를 import해준 다음 User.findByToken();
이라는 메서드를 일단 써놓고, findByToken을 만들러 User로 가자.
userSchema.statics.findByToken = function(token, cb) {
let user = this;
// 가져온 토큰을 복호화
jwt.verify(token, "secretToken", function(err, decoded){
// 유저 아이디로 유저를 찾은 후
// 클라이언트에서 가져온 token과 DB의 token이 일치하는지 확인
user.findOne({_id: decoded, token: token}, function(err, user){
if(err) return cb(err);
cb(null, user);
})
})
}
왜 이번에는 method가 아니라 statics를 썼는지 궁금..
저 verify부분은 jsonwebtoken 문서에도 예시가 있다.
그러면 이제 저 메서드를 통해서 err또는 user가 넘어올 것이다.
findByToken
메서드 처리를 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();
})
전체적으로 보면 이러하다
그러니, 위에 작성한 부분에서 err 또는 decoded(user._id
)를 통해서 err나 인증된 user를 넘겨주면, 이걸 받아서 req에다가 token과 user를 저장해주고 next()
를 이용해 다음 순서로 넘겨준다.
위에 작성한 부분은 여기 auth(미들웨어)부분에서 수행되는 것임.
next()
를 통해 비로소 auth를 넘어 다음 국면으로 접어든다.