2022이전/node.js

JWT (Json Web Token)

바로퇴장 2020. 1. 6. 17:29

JWT (Json Web Token)

JWT 란?

JSON Web Token의 약자로 클레임 토큰 기반 인증 방식입니다. 클라이언트의 세션 상태를 저장하는 것이 아니라 필요한 정보를 토큰 body에 저장해서 클라이언트가 가지고 이를 증명서 처럼 사용

JWT의 구성

{Header}, {Payload}, {Verify Signature} 3가지 정보를 '.'로 연결하여 사용한다.

Header : JWT 토큰의 유형이나 사용된 해시 알고리즘의 정보가 들어간다.

PayLoad : 클라이언트에 대한 정보가 담겨있다. 또한 여기에는 iss,sub,aud,exp,nbf,lat,jti 와 같은 기본 정보가 들어간다.

Signature : header에서 저장한 알고리즘과 secret key로 Header와 Payload를 담는다.

payload는 공개데이터로 비밀번호와 같은 보안이 필요한 정보는 payload에 저장하면 안됩니다.

JWT의 Secret Key는 정보는 공개가 되어있지만 해시 값을 통해서 정보가 유효한지 확인을 하게 됩니다. 따라서 시크릿키가 유축된다면 JWT에 보안상에 큰 위협이 됩니다.

JWT 과정

로그인(토큰 발행)

  1. 클라이언트가 유저에 대한 정보를 서버에게 보낸다.
  2. 서버는 DB를 이용해서 정보의 유효성을 확인한다.
  3. User 정보 중 일부를 JWT body에 넣고 토큰을 발행
  4. 클라이언트에게 응답한다.

토큰 검증과정

  1. HTTP header에 토큰값을 넣어서 보낸다.
  2. 서버는 토큰값을 받아서 JWT 정보와 서버가 가지고 있는 secret key를 이용해서 서명을 만든다.

실습 예제

Jwt.js

const jwt = require('jsonwebtoken');
const secretOrPrivateKey = "jwtSecretKey";

const options = {
    algorithm: "HS256",
    expiresIn: "1d",
    issuer: "withDev"
}

const refreshOptions = {
    algorithm: "HS256",
    expiresIn: "1d",
    issuer: "withDev"
}
module.exports = {
    sign: (user) => {
        const payload = {
            userIdx : user.userIdx,
            name : user.name,
            email : user.email
        };
        const result = {
            token: jwt.sign(payload, secretOrPrivateKey, options)           
        };

        return result;
    },    

    verify: (token) => {

        let decoded;
        try{
            decoded = jwt.verify(token,secretOrPrivateKey);
        } catch (err){
            if (err.message === 'jwt expired') {//유효기간 만료
                console.log('expired token');
                return -3;
            } else if (err.message === 'invalid token') {//잘못된 token
                console.log('invalid token');
                return -2;
            } else {
                console.log("error");
                return -2;
            }
        }
        return decoded;//error가 없을 시에 decoded로 return을 한다. 
        }

    } 

Authutil.js

const jwt = require('./jwt');

const authMiddleware = {
    //middleware
    //미들웨어로 token이 있는지 없는지 확인하고
    //token이 있다면 jwt.verify함수를 이용해서 토큰 hash를 확인하고 토큰에 들어있는 정보 해독
    validToken: async(req, res, next) => {
        const token = req.headers.token;
        if(!token){
            return res.json(util.successFalse(statusCode.BAD_REQUEST, resMessage.EMPTY_TOKEN));
        } else{
            const user = jwt.verify(token);            
            req.decoded = user;            
            next();
        }
    }   
};
module.exports = authMiddleware;