Jello's development blog

Jello's development blog

로그인에 JWT(JSON Web Token)사용하기

JWT란?

JSON Web Token의 약자로, 일반적으로 HTTP API 서버를 만들 때에 인증 방법으로 사용한다.
서버는 사용자가 로그인 할 때 고유한 Token을 생성하고, 이를 사용자에게 알려주어 사용자가 다른 API를 사용할 때에 헤더에 이 Token을 넣으면, 자신이라는 것을 증명할 수 있게 하는 것이다.

JWT의 구조

https://jwt.io/ 에 가보면 JWT가 어떤 구조로 되어있는지 간단하게 볼 수 있다.

https://jwt.io/

Encoding된 Token을 보면 .을 기준으로 세 부분으로 구분되는데, HEADER, PAYLOAD, VERIFY SIGNATURE로 구분된다.

  • HEADER : 암호화 알고리즘, Token의 type
  • PAYLOAD : 데이터
  • VERIFY SIGNATURE : 데이터에 대한 무결성, 위조 방지를 위한 HMAC(해시 기반 메시지 인증 코드)

여기서 일반적으로 PAYLOAD에 사용자의 정보를 넣어서 사용한다.

JWT를 직접 구현하는 것은 보안성, 생산성 측면에서 좋지 않으니 https://jwt.io/의 하단(Libraries)에서 지원하는 패키지&모듈을 찾아서 사용하면 좋을 것 같다.

Express에서 JWT 사용하기

Node.js 기반의 Express 서버에서 JWT를 사용해보자. Node.js에서는 jsonwebtoken이라는 패키지가 제공된다.

ORM은 Sequelize를 사용하였다.

User Token 생성 함수

getToken: function() {
    var token = jwt.sign({
        id: this.id
    }, secret);
    return token;
}

jsonwebtoken에서 제공하는 jwt.sign함수를 이용하여 token을 생성한다. 보안을 위하여 User의 모든 정보를 PAYLOAD에 담지는 않도록 하였다.

Login시 User Token 보내기

router.post('/login', function(req, res) {
    db.users.findOne({
        where: { email: req.body.email }
    }).then(function(user) {
        if(user && cipher(req.body.password) === user.password){
            res.json({
                token: user.getToken()
            });
        }else{
            throw err
        }
    }).catch(function(err) {
        ...
    });
});

먼저 User를 DB에 저장한 뒤에, 로그인할 때에 아이디와 패스워드를 확인한다. 확인이 제대로 됐다면 위에서 설명한 getToken을 이용하여 response한다.

이제 사용자(Front-End)는 이 토큰을 웹페이지에 가지고 있고, User 인증이 필요한 API(e.g., 사용자 정보 보기, 글 삭제, etc)를 호출할 때에 request header에 token을 넣어서 보낸다.

인증 함수 미들웨어

function(req, res, next) {
    var token = req.get('accessToken');

    if(typeof token !== 'undefined'){
        var decoded = jwt.verify(token, secret);
        db.users.findById(decoded.id).then(function(user) {
            req.user = user;
            next();
        }).catch(function(err) {
            res.status(400).send(err.message);
        });
    }else{
        res.sendStatus(403);
    }
};

헤더에서 token이 담긴 accessToken를 읽어온 뒤에, jwt.verify함수를 이용하여 암호화된 JWT의 PAYLOAD를 decoded라는 변수에 저장하였다. PAYLOAD에는 User의 id가 저장되어있기 때문에, 그 id를 가지고 DB를 조회한다. User의 정보를 얻었으니 이를 통해서 하고싶은 것을 하면 된다.