[Node.js Login] 03 Auth 기능 만들기

2022. 9. 10. 17:08·Backend

이 글에서는 user가 로그인한 후 생성된 token을 가지고 user를 인증(authentication)하는 기능을 만든다.

(이전 글과 이어짐)


1. Token을 이용한 Auth 과정

이전 글에서 token이 어떻게 쓰이는지 설명했었는데, 다시 상기시켜보자.

client의 token은 client쪽과 server쪽에 동일하게 저장되어 있고, token은 client가 server에게 새로운 요청을 보낼 때 'it's me' 의 용도로 함께 보내진다. server는 그 token을 받아서 decode하고, decode한 결과 즉, user의 id를 DB에 검색한다. server는 id가 일치하는 user의 정보에 있는 token과 client에게 받은 token을 비교한다. 둘이 서로 일치하면 인증에 성공한 거고 일치하지 않으면 인증에 실패한 것이다.

 

인증 과정이 저러하니 다음의 과정을 거쳐 코드를 짜보자.

  1. 일단 인증을 위한 route를 하나 만든다.
  2. client로부터 token을 받고, token을 decode한다.
  3. decode한 결과를 DB에서 검색하고, DB에 저장되어 있는 해당 user의 token을 2에서 받은 token과 비교한다.
  4. 비교 결과가 같으면 (=인증에 성공하면) user의 요청에 대한 응답을 보낸다.

 

 

2. auth middleware 만들기

난데없이 미들웨어가 뭐냐. 아래는 미들웨어에 대한 document 설명이다.

미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트(res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수에 대한 액세스 권한을 갖는 함수입니다. 그 다음의 미들웨어 함수는 일반적으로 next 라는 이름의 변수로 표시됩니다.

next라면 저번에 bcrypt로 비밀번호 hash 처리할 때 쓴 적이 있다. 아하, 이게 그거구나.

미들웨어 함수가 next, 즉 이다음에 실행할 함수에 대한 접근 권한을 체크한다고 했으니까 auth 기능을 미들웨어로 만들면 딱 알맞을 것 같다.

 

auth라는 route를 만들고, auth라는 미들웨어 함수를 만들어준다. auth 미들웨어 함수를 만들 때, 나는 관리하기 편하도록 middleware라는 폴더를 새로 만들고 auth.js 파일을 만들었다.

middleware/auth.js

/* 인증 처리 */
let auth = (req, res, next) => {
    //클라이언트 쿠키에서 토큰을 가져옴
    let token = req.cookies.x_auth; //전에 x_auth라는 이름으로 토큰을 쿠키에 저장했음
    
    //토큰을 복호화한 후 user를 DB에서 찾음
    // user를 찾았으면 token 비교
}

module.exports = { auth };

토큰을 복호화하고, 복호화한 결과값을 DB 내에서 찾는 것은 아래 3에서 할 것이다.

 

index.js

const { auth } = require('./middleware/auth');
app.get('/auth', auth, (req, res) => {
    /* auth 함수 실행 후 이 곳이 실행됨 */
})

 

 

3. Token을 decode하여 DB 내에서 user 찾기

token decode는 jwt의 verify를 이용하면 된다. token과 key를 넣으면 복호화를 해준다.

3번 과정은 User.js에 findByToken 이라는 메소드를 만들어서 처리할 것이다.

 

User.js

/* token 복호화 & DB에서 복호화한 결과(id) 검색*/
userSchema.statics.findByToken = function (token, callback) {
    var user = this;

    // 토큰 decode
    jwt.verify(token, 'secretKey', function (err, decoded) {
        // decoded(=user id), token을 DB에서 검색
        user.findOne({ "_id": decoded, "token": token }, function (err, user) {
            if (err) return callback(err);
            callback(null, user);
        })
    })
}

모델 메소드를 만들 때 그동안은 .methods를 썼는데, 이번에는 .statics를 사용했다. 둘의 차이점은 아래와 같다.

  • statics : this가 model 자체를 가리킴
  • methods : this가 호출한 녀석(data instance)를 가리킴

여기서 statics를 쓴 이유는, findOne을 쓰기 위해서이다(findOne 메소드가 model에서 작동하므로).

 

만든 메소드를 auth 미들웨어 함수에서 쓴다.

middleware/auth.js

const { User } = require('../models/User');

/* 인증 처리 */
let auth = (req, res, next) => {
    let token = req.cookies.x_auth;

    //토큰을 복호화한 후 user를 DB에서 찾음
    User.findByToken(token, (err, user) => {
        if (err) throw err;
        if (!user) return res.json({ isAuth: false, error: true })

        // user를 찾았으면 auth를 호출한 곳에서도 token, user를 쓸 수 있게 보내주고 next() 해줌
        req.token = token;
        req.user = user;
        next();
    })
}

module.exports = { auth };

 

 

 

4. 인증된 user이면, client에게 요청에 대한 정보를 응답해줌

index.js

const { auth } = require('./middleware/auth');

app.get('/auth', auth, (req, res) => {
    // 여기 도달했다는 것은 auth를 무사히 통과했다는 뜻 = 인증된 user라는 뜻
    // auth에서 err가 나거나 auth:false거나 하면 여기 오지 못함

    // 클라이언트에게 전달하려는 user 정보를 전달해줌
    res.status(200).json({
        _id: req.user._id,
        isAdmin: req.user.role === 0 ? false : true,
        isAuth: true,
        name: req.user.name,
        email: req.user.email,
        lastname: req.user.lastname,
    })
})

주석에 써있듯, 여기 도달한 것은 인증된 user임을 뜻한다. 따라서 바로 user 정보를 전달해준다.

isAdmin은 user가 관리자인지 아닌지를 나타내는 건데, 처음에 User 모델을 만들 때, 일반 사용자는 role을 0으로, 관리자는 1로 설정하기로 정했어서 저렇게 쓴거다.

 

 

5. auth 기능 테스트

auth 기능을 테스트하려면 DB에 auth하려는 user의 정보가 있어야 하고(register), 로그인된 상태여야 한다. 만약 register, login이 안 된 상태라면 이전글과 이 전전글을 참고해서 register, login을 해준 다음 테스트를 진행하자.

 

테스트는 간단하다. 만든 auth route로 send하면 인증 결과에 따라 user 정보를 받거나, 받지 못할 수 있다.

auth에 성공한 경우
auth에 실패한 경우

 

저작자표시 (새창열림)

'Backend' 카테고리의 다른 글

MongoDB와 Node express 연결하기  (0) 2023.02.08
React와 Node.js 연동하기  (0) 2023.02.03
[Node.js login] 04 Logout 기능 만들기  (0) 2022.09.10
[Node.js Login] 02 로그인 정보와 DB 데이터 비교하여 로그인하기 & Token 만들기 (using jsonwebtoken)  (0) 2022.09.09
[Node.js Login] 01 Bcrypt를 이용해 비밀번호를 암호화하여 DB에 저장하기  (0) 2022.09.08
'Backend' 카테고리의 다른 글
  • React와 Node.js 연동하기
  • [Node.js login] 04 Logout 기능 만들기
  • [Node.js Login] 02 로그인 정보와 DB 데이터 비교하여 로그인하기 & Token 만들기 (using jsonwebtoken)
  • [Node.js Login] 01 Bcrypt를 이용해 비밀번호를 암호화하여 DB에 저장하기
톱치
톱치
나를 위한 기록을 합니다
  • 톱치
    기록
    톱치
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • 홈
    • 방명록
    • 글쓰기
    • 전체보기 (51)
      • Articles (0)
      • Frontend (3)
        • JS, TS (16)
        • HTML, CSS (5)
        • React (6)
        • Dart (3)
      • Backend (6)
      • Others (3)
      • Algorithm (5)
      • 회고 (4)
  • 링크

    • GitHub
  • 태그

    dart
    js
    todolist
    programmers
    Redux
    프리코스
    login
    Node
    React
    node.js
    javascript
    TypeScript
    css
    우아한테크코스
    BCrypt
    ts
    회고
    token
    object
    BFS
  • hELLO· Designed By정상우.v4.10.3
톱치
[Node.js Login] 03 Auth 기능 만들기
상단으로

티스토리툴바