authentication기능을 만들기위해 auth라는 라우터를 새로 만들려고합니다.
auth는 왜 필요할까요??
어떤 사이트에 들어갔을때 사이트에 여러가지 페이지가 있습니다.
어떤페이지는 로그인 된 유저들만 이용할수 있고 어떤 페이지는 누구나 이용할수 있는 페이지가 있을것입니다.
예를 들면 게시글을 작성할때 로그인 된 유저가 글을 쓸수 있겠지만 또 어떤 게시글은 관리자(admin)만 글을 쓸수 있을수 있습니다.
그런 것을 하나하나 체크해주기 위해 authentication기능을 만드는 것입니다.
지난번 포스팅에서 토큰을 만들어 서버(데이터베이스)에 넣어주고 그 토큰을 클라이언트(쿠키)에도 넣어주었습니다.
그래서 두가지를 이용해서 두가지 토큰이 맞는지를 체크하여 A페이지에서 B페이지로 넘어갈때 이 유저가 B페이지로 넘어갈수 있는 권한이 있는지 클라이언트에서 쿠키에 담겨있는 토큰을 서버에 전달을 하게 됩니다.
전달할때 토큰이 인코드 되어있기 때문에 디코드를 하면 유저 ID가 나오게 됩니다.
그 유저ID로 데이터베이스에 해당 유저의 토큰이 있다면 인증이 되는것이고 토큰이 없거나 다르면 권한을 제한하는 것입니다.
// index.js
app.get('/api/users/auth', auth, (req, res) => {
});
이번에는 get방식으로 api를 만들어 볼건데요.
이번에는 중간에 auth라는 아규먼트가 들어가있네요.
auth를 미들웨어라고 하는데 middleware라는 폴더를 만들어서 auth.js 파일을 만들어보겠습니다.
// auth.js
const { User } = require("../model/User");
let auth = (req, res, next) => {
// 인증 처리를 하는곳
// 클라이언트 쿠키에서 토큰을 가져온다.
let token = req.cookies.x_auth;
// 토큰을 복호화 한후 유저를 찾는다.
// 유저가 있으면 인증O
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();
});
// 유저가 없으면 인증X
}
module.exports = { auth };
auth.js파일에는 이런 기능을 구현해놓았는데요.
위에서 말했던것처럼 클라이언트에서 토큰을 가져와서 복호화를하고 해당 유저를 찾는 과정입니다.
이전에 토큰을 x_auth라는 이름으로 클라이언트에 저장을 해놓았기 때문에
let token = req.cookie.x_auth;
요청데이터중 저장된 쿠키의 x_auth를 가지고옵니다.
User.findByToken()
User에서 findByToken()이라는 함수를 실행시킬건데요.
User에 findByToken()이라는 함수를 만들어야합니다.
// User.js
userSchema.statics.findByToken = function(token, callback) {
var user = this;
// 토큰을 decode 한다.
jwt.verify(token, 'secretToken', function(err, decode) {
// 유저 아이디를 이용해서 유저를 찾은 다음에 클라이언트에서 가져온 token과 DB에 있는 token이 일치하는지 확인
user.findOne({"_id": decode, "token": token}, function(err, user) {
if(err) return callback(err);
callback(null, user);
});
});
}
토큰을 만들기위해 사용했던 jwt를 이용하여 다시 복호화를 할건데요.
이전에 토큰을 만들기위해 _id와 문자열 secretToken을 이용했었던것처럼 이번에는 secretToken을 분리시켜보겠습니다.
이렇게 분리되어 찾은 user id를 찾아 DB의 토큰과 클라이언트에서 가져온 토큰이 일치하는지를 확인합니다.
만약 일치하지 않는다면 err를 콜백하고 일치한다면 user를 콜백합니다.
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가 있다면 에러를 던지고
에러는 없지만 유저가 없다면 위의 결과를 반환합니다.
하지만 만약 인증이 성공했다면 token과 user를 초기화해줍니다.
// index.js
app.get('/api/users/auth', auth, (req, res) => {
// 여기까지 미들웨어를 통과했다면 Authentication이 True라는 말
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,
});
});
이 라우터안으로 들어왔다는 이야기는 미들웨어인 auth가 성공하여 ture라는 의미입니다.
따라서 응답을 하게 되는데 상태는 200으로 성공한 상태를 리턴하며 id를 포함한 각 데이터를 리턴합니다.
'따라하며 배우는 시리즈 > NodeJS & ReactJS Basic' 카테고리의 다른 글
[ReactJS] Create React App(리액트 개발환경 설정) (0) | 2022.09.09 |
---|---|
[NodeJS] 노드 리액트 기초 - 로그아웃 기능 만들기 (0) | 2022.09.08 |
[NodeJS] 노드 리액트 기초 - bcrypt를 이용한 로그인 기능 만들기 (0) | 2022.09.06 |
[NodeJS] 노드 리액트 기초 - Bcrypt로 비밀번호 암호화 하기 (0) | 2022.09.05 |
[NodeJS] 노드 리액트 기초 - 비밀 설정 정보 관리(모듈 이용해서 비밀정보 관리) (1) | 2022.09.02 |