JWT 적용하기




1. JWT 토큰이 뭐야?

  • Json Web Token
  • JSON 객체를 사용하여 가볍고 자가수용적인 (self-contained: 필요한 모든 정보를 자체적으로 지님) 방식으로 정보를 안전성 있게 전달하는 Web Token
  • 유저 인증을 하는 토큰을 클라이언트의 쿠키에 저장할건데, 쿠키는 노출이 쉬우므로 민감한 데이터가 담겨 있으면 안된다.
  • 따라서 jwt 토큰을 활용하여 암호화된 토큰을 발급하는 것✨



JWT 구조

jwt

aaaaa.bbbbb.ccccc 세 부분으로 이루어져 있다.

  • header : type(토큰의 타입), alg(해싱 알고리즘)
  • payload : 토큰에 담을 정보 (iss, sub, exp …)
  • signature : 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드 signature 는 header와 payload의 값을 각각 BASE64로 인코딩하고,
    인코딩한 값을 비밀 키를 이용하여 header에서 정의한 알고리즘으로 해싱한 후,
    이 값을 다시 BASE64로 인코딩하여 생성한다.



JWT 단점

  • 모든 사용자들의 상태를 기억하고 있지 않다.
  • 이미 발급한 토큰을 뺏을 수 없다.
  • 따라서 해커에게 토큰이 빼앗겼다면 무효화할 수 없다.



단점 해결법

  • accessToken, refreshToken 2개를 발급해준다.
  • accessToken : 유효 기간이 짧다. (3h)
  • refreshToken : 유효 기간이 길다. (보통 2주)
  • 로그인시 accessToken, refreshToken을 발급해주고, accessToken 만료 시, refreshToken이 유효하면 accessToken을 재발급해준다.



2. JWT 적용하기

JWT 설치 및 세팅

npm install --save jsonwebtoken 해당 명령어를 통해 jsonwebtoken 을 설치하자.

config/jwt.js

const jwtConfig = {
  secretKey: process.env.JWT_ACCESS_SECRET,
  refeshSecretKey: process.env.JWT_REFRESH_SECRET,
  option: {
    algorithm: 'HS256',
    expiresIn: process.env.JWT_ACCESS_TIME,
    issuer: 'movester',
  },
  refeshOption: {
    algorithm: 'HS256',
    expiresIn: process.env.JWT_REFRESH_TIME,
    issuer: 'movester',
  }
};

header, payload, signature에 담을 데이터 옵션을 세팅해놓는다.
secretKey는 보안에 직결되므로 env 변수를 활용하였다.
accessToken은 expiresIn을 짧게, refreshToken은 길게 설정한다.


JWT 토큰 발급

modules/jwt.js

const signAccessToken = async user => jwt.sign(user, jwtConfig.secretKey, jwtConfig.option);

jwt 관련 메소드를 재사용하기 위해 modules 폴더에 별도로 분리하였다.

service/admin.js

const jwt = require('../modules/jwt');
//login logic ...
const token = {
      accessToken: await jwt.signAccessToken({ idx: admin.admin_idx, email: admin.email }),
      refreshToken: await jwt.signRefreshToken({ idx: admin.admin_idx, email: admin.email }),
    };

jwt.sign(payload, secretKey, [options])
jwt는 sign 함수로 토큰을 발급받는다.
나는 payload로 idx, email 값을 주었다. (토큰 decode시 유저의 idx, email 얻기 위해)



JWT 토큰 검증

modules/jwt.js

const verifyAccessToken = async token => {
  try {
    return jwt.verify(token, jwtConfig.secretKey);
  } catch (err) {
    console.log('token invalid');
  }
};

jwt.verify(toekn, secretKey)
jwt는 verify 함수로 토큰을 검증한다.

middleware/auth.js

const accessToken = await jwt.verifyAccessToken(req.cookies.accessToken);


verify되어 나온 결과값을 담은 accessToken은 유효한 토큰이었다면,

{
  idx: 8,
  email: 'minsung',
  iat: 1643200950,
  exp: 1643204550,
  iss: 'movester'
}

다음과 같이 토큰을 발급할 때 입력한 payload를 준다.
유효하지 않은 토큰이라면, undefined를 준다. (try-catch문에서 err로 평가되므로 주의하자.)


지금까지 jwt 가 무엇이고, node 환경에서 어떻게 토큰을 발급받고 검증하는지를 알아보았다.
다음에는 accessToken과 refreshToken을 활용하는 방법에 대해 알아보자.🏋️‍♂️