옹실이의 개발이야기

Node.js

Authentication 기능 만들기

옹실 2021. 11. 7. 21:21

웹사이트를 이용하다보면 특정 페이지는 접속 유저에 따라 권한이 다른 경우가 있다.
예를 들면, 쇼핑몰 웹에 접속했을 때 마이 페이지는 로그인 유저만 이용할 수 있고,
제품 등록 및 관리 페이지는 관리자만 이용할 수 있다.

이처럼 한 사이트에서 권한별로 이용할 수 있는 페이지가 다르기 때문에 
접속 유저별로 권한을 체크하는 Authentication 기능이 필요하다. 

오늘은 Auth(편의상 줄여서 표시하겠음) 기능을 만들어보려고 한다.
auth 기능을 만들려면 auth route를 만들어야 한다.

진행 방식 및 로직은 다음과 같다.
저번 포스팅에서 로그인한 유저의 정보를 쿠키에 저장했는데,
유저가 로그인 후 특정 페이지 접속 시 쿠키에 있는 유저의 정보(토큰)를 가져와서
DB에 저장되어있는 유저의 정보(토큰)와 비교하고, DB에 해당 유저의 토큰이 있는지 확인한다.
※ 쿠키에 유저의 정보를 인코딩(암호화) 해서 저장했기 때문에,
   DB에 있는 정보와 비교하기 위해서는 디코딩(복호화) 작업이 필요하다.

 

Auth route 만들기

   1. index.js에서 인증처리 하는 메소드 만든다
   2. 사용자의 인증을 처리하는 미들웨어 auth 메소드를 만든다.


* 참고사항 *
진행방식 : User.js(User 스키마)에서 User 관련 function 만든 후 Index.js에서 호출
사용한 라이브러리/프로그램(서비스) : jsonwebtoken, cookie-parser
DB : MongoDB(몽고DB)


 

1. index.js - 인증처리 확인하는 메소드 만든다

유저가 get 방식으로 요청 시 권한을 체크해 인증을 처리하고
맞으면 정상코드(200) + 유저 정보를 리턴해주는 메소드를 만들어준다.
인증 처리는 해당 메소드 내에서 자체적으로 하는 것이 아니라 auth라는 미들웨어 메소드를 이용할 것이다.

※ 미들웨어 : 중간다리 역할이라고 생각하면 된다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const { auth } = require('./middleware/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
  })
})
cs

진행흐름 : 클라이언트 /api/users/auth 로 요청 -> 미들웨어 auth 거쳐서 인증 OK -> 콜백함수 (req, res)
- 인증이 OK됐을 경우 인증에 성공했다는 표시로 status 코드 200과 user스키마에 있는 정보를 return한다.
 (user 스키마에 해당 유저의 정보가 저장되어 있다.)

/api/user/auth는 일종의 주소로, product나 mypage 등 항목별로 라우터가 다양해질 수 있기 때문에
특정 단어로 정리했다. user의 auth(권한)을 체크하고 인증처리하는 곳이니까 /api/users/auth로 설정했다.

auth는 미들웨어로 내가 정한 함수 이름이다. ( 이름은 다른걸로 바꿔써도 된다. )
클라이언트가 get방식으로 /api/users/auth에 요청하면 콜백함수(req, res) 호출 전에 중간에서 호출된다.
여기서는 유저의 권한 확인을 통해 인증처리하는 기능을 제공할 것이다.
아직 명시하지 않았지만, index.js가 있는 폴더 위치 밖에 middle웨어라는 폴더를 하나 만든 후
그 안에 auth.js 라는 파일을 만들고 auth라는 함수를 만들 예정이다.

※ index.js 기준으로 봤을때 외부에서 만든 함수를 사용해야하기 때문에
   require로 auth를 import를 해주었다.
   require 안에 있는 ('./middleware/auth')는 index.js 기준으로 호출할 auth 메소드의 경로이다.

 

isAdmin: req.user.role === 0 ? false : true 는 0이면 false, 아니면 true를 반환하겠다는 것으로,
0 이면 일반유저, 0이 아니면 다른 유저로 간주하는 걸로 설정했다.

 

2. 사용자의 인증을 처리하는 미들웨어 auth 메소드를 만든다.

위에서 적었듯이 index.js가 위치한 폴더 밖에 middle웨어라는 폴더를 하나 만든 후
그 안에 auth.js 라는 파일을 만들고 auth라는 함수를 만들어준다.

auth 메소드는 인증을 처리하는 곳으로
쿠키에 있는 토큰 정보를 가져와 해당 토큰이 유저 스키마에 있는지 확인해
토큰이 DB에 저장되어있다면 request에 토큰과 user 정보를 넣어주고,
없다면 err + isAuth : false + error true를 리턴한다.
(해당 토큰이 유저 스키마에 있는지 확인하는 것은
유저 스키마에서 토큰을 찾는 findByToken메소드를 만들어 사용할 것이다.)

인증이 OK됐을 경우 request에 user 정보와 토큰을 넣어주는 이유는
여기서 넣어주면 index.js에서 request로 user정보와 token 정보를 가져올 수 있기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 } ;
cs

해당 토큰이 유저 스키마에 있는지 여부는
models 폴더 안에 있는 User.js에서 만들어서 사용할 것이기 때문에 require로 import 시켰다.

쿠키 parser를 이용해 request로 x_auth라는 이름의 쿠키 정보(토큰)를 갖고와서
token이라는 변수에 담았다.
(여기서 x_auth는 유저의 토큰 정보를 저장할때 지정한 쿠키의 이름이다.)

메소드 마지막에는 해당 메소드 실행 후 다음 메소드를 실행시킬 수 있도록 next()를 적었다.
(auth() 메소드는 위에서 적었듯이 미들웨어이기 때문에 auth() 다음에 나오는 함수를 호출해주어야 한다.
오류가 났을 경우 next()까지 못 오고 중간에서 빠져나가게 된다.)

맨 마지막으로 auth 메소드를 exports 시켜서
다른 곳에서 이 메소드를 import해서 사용할 수 있도록 만들었다.