JWT 사용방법

Node.js에서 제일 사용량이 많은 jsonwebtoken 라이브러리를 사용하자

 

# yarn을 이용해 프로젝트를 초기화합니다.
yarn init -y

# jsonwebtoken, express 라이브러리를 설치합니다.
yarn add jsonwebtoken express
  • yarn을 이용해 생성된 package.json 파일에서 type을 module로 변경하자 ( 프로젝트에서 ES6 모듈을 사용할수 있도록 설정해주는 옵션 )

JSON 데이터를 암호화

  • jsonwebtoken 라이브러리의 sign 메서드를 사용해 JWT를 생성한다.
import jwt from 'jsonwebtoken';

const token = jwt.sign({ myPayloadData: 1234 }, 'mysecretkey');
console.log(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0
  • sign 메서드는 첫 번째 인자로 Payload 데이터를, 두 번째 인자로 비밀 키를 받아 JWT를 생성한다. ( 여기서, Payload는 문자열 뿐만 아니라, 객체도 할당할 수 있다 )

JWT로 만든 토큰 모습

 

JSON 데이터를 복호화

  • jsonwebtoken 라이브러리의 decode 메서드를 사용해  JWT를 복호화한다.
import jwt from 'jsonwebtoken';

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0";
const decodedValue = jwt.decode(token);

console.log(decodedValue); // { myPayloadData: 1234, iat: 1690873885 }
  • JWT는 누구나 복호화가 가능하다. 하지만 검증을 통해 변조가 되지 않은 데이터인지 알 수 있다.

복호화 된 JWT 출력

 

복호화가 아닌, 변조되지 않은 데이터 검증해보기

  • jsonwebtoken 라이브러리의 verify 메서드를 사용해 JWT를 검증한다.
import jwt from 'jsonwebtoken';

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0";
const decodedValueByVerify = jwt.verify(token, "mysecretkey");

console.log(decodedValueByVerify); // { myPayloadData: 1234, iat: 1690873885 }
  • JWT가 변조되지 않았고, 올바른 비밀 키로 서명되었는지를 검증하는 중
  • 검증에 실패하면 에러가 발생한다.

잘못된 비밀키를 입력해서 데이터를 검증해보기

  • 잘못된 비밀 키를 이용해 JWT를 검증하면, 에러가 발생한다.
import jwt from 'jsonwebtoken';

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0LCJpYXQiOjE2OTA4NzM4ODV9.YUmYY9aef9HOO8f2d6Umh2gtWRXJjDkzjm5FPhsQEA0";
const decodedValueByVerify = jwt.verify(token, "secretkey");

console.log(decodedValueByVerify);

// JsonWebTokenError: invalid signature
  • mysecretkey를 secretkey로 변경해서 실행해보자 ( 그러면 아래와 같은 에러가 발생하게되어, 검증에 실패했다는 것을 확인할 수 있다. )

Invalid Signature 에러 발생


JWT를 써야 하는 이유

JWT는 두 가지 중요한 특징을 가지고 있다.

  • JWT가 인증 서버에서 발급되었는지 위변조 여부를 확인할 수 있다.
  • 누구든지 JWT 내부에 들어있는 정보를 확인할 수 있다. ( 복호화 )

만약 JWT를 사용하지 않은 상태에서 사용자 로그인을 구현하려고 하면 어떻게 될까?

 

JWT를 적용하지 않은 로그인 API를 만들어보자

import express from 'express';
const app = express();

app.post('/login', function (req, res, next) {
  const user = { // 사용자 정보
    userId: 203, // 사용자의 고유 아이디 (Primary key)
    email: "archepro84@gmail.com", // 사용자의 이메일
    name: "이용우", // 사용자의 이름
  }

  res.cookie('sparta', user);  // sparta 라는 이름을 가진 쿠키에 user 객체를 할당합니다.
  return res.status(200).end();
});

app.listen(5002, () => {
  console.log(5002, "번호로 서버가 켜졌어요!");
});
  • 사용자의 정보가 sparta 이름을 가진 쿠키에 할당된다.
  • 쿠키의 속성값이나 만료 시간을 클라이언트가 언제든지 수정할 수 있다
  • 쿠키의 위변조 여부를 확인 할 수 없다.

 

JWT를 적용한 로그인 API를 만들어보자

import express from 'express';
import JWT from 'jsonwebtoken';

const app = express();

app.post('/login', (req, res) => {
  // 사용자 정보
  const user = {
    userId: 203,
    email: 'archepro84@gmail.com',
    name: '이용우',
  };

  // 사용자 정보를 JWT로 생성
  const userJWT = JWT.sign(
    user, // user 변수의 데이터를 payload에 할당
    'secretOrPrivateKey', // JWT의 비밀키를 secretOrPrivateKey라는 문자열로 할당
    { expiresIn: '1h' }, // JWT의 인증 만료시간을 1시간으로 설정
  );

  // userJWT 변수를 sparta 라는 이름을 가진 쿠키에 Bearer 토큰 형식으로 할당
  res.cookie('sparta', `Bearer ${userJWT}`);
  return res.status(200).end();
});

app.listen(5002, () => {
  console.log(5002, '번호로 서버가 켜졌어요!');
});
  • 사용자의 정보를 Payload에 저장한 JWT를 sparta 이름을 가진 쿠키에 할당된다.
  • JWT를 생성할 때 위변조 여부를 확인할 수 있는 비밀키를 사용했다.
  • 쿠키의 만료시간과 별개로 JWT의 만료시간을 설정했다.

 

암호화 된 데이터의 사용 방법

보통 암호화 된 데이터는 클라이언트 ( 브라우저 ) 가 전달받아 다양한 수단 ( 쿠키, 로컬스토리지 등 )을 통해 저장해 API 서버에 요청을 할 때 서버가 요구하는 HTTP 인증 양식에 맞게 보내주어 인증을 시도한다.

 

+ Recent posts