JWT (JSON Web Tokens)

박재현·2021년 12월 22일
1
post-custom-banner

JWT

// npm i jsonwebtoken
const jwt = require('jsonwebtoken');

// 토큰 생성, 시크릿 키: 'my-secret-key'
const token = jwt.sign({ test: true }, 'my-secret-key');
console.log(token);
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0Ijp0cnVlLCJpYXQiOjE2NDAxNzI3NTN9._Nu27p4dDeGdvjncA_mBFZFEYNxWVeuGdkK2DJzdG1Y

// 복호화
const decoded = jwt.decode(token)
console.log(decoded)
// { test: true, iat: 1640173279 }

// 정상적인 토큰인지 검증
const verify = jwt.verify(token,"my-secret-key")
console.log(verify)
// { test: true, iat: 1640173279 }
// 만약 시크릿키가 정상적이지 않다면 error 발생

// 머리(HEADER).가슴(PAYLOAD).배(VERIFY SIGNATURE) 로 생성이되며
// jwt.io에서 해당 token을 입력해 보면 
// 가슴(payload)에 해당 데이터인 {"test": true} 을 담고 있다.
// 누구나 해당 사이트에서 Encoded(복호화)를 통해 데이터를 확인할 수는 있지만
// 변조가 불가능하며
// 배(VERIFY SIGNATURE)에 시크릿키(여기서는 "my-secret-key")를 입력해야
// 해당 데이터가 정상적인 토큰인지 signature verified 할 수 있다.  

요약

  • JSON 형태의 데이터를 안전하게 교환하여 사용
  • 인터넷 표준으로서 자리잡은 규격입
  • 여러가지 암호화 알고리즘을 사용
  • header.payload.signature 의 형식으로 3가지의 데이터를 포함 (개미처럼 머리, 가슴, 배)
    때문에 JWT 형식으로 변환 된 데이터는 항상 2개의 . 이 포함된 데이터

형태

https://jwt.io/ 에서 간단히 확인가능

  • header(머리)는 signature(배)에서 어떤 암호화를 사용하여 생성된 데이터인지 표현
  • payload(가슴)는 개발자가 원하는 데이터를 저장
  • signature(배)는 이 토큰이 변조되지 않은 정상적인 토큰인지 확인

특성

  • JWT는 암호 키를 몰라도 Decode가 가능
    변조만 불가능 할 뿐, 누구나 복호화하여 보는것은 가능
  • 때문에 민감한 정보(개인정보, 비밀번호 등)는 담지 않도록 해야함
  • 특정 언어에서만 사용 가능한것은 아님
    단지 개념으로서 존재하고, 이 개념을 코드로 구현하여 공개된 코드를 우리가 사용하는게 일반적

쿠키, 세션과 다른점

데이터를 교환하고 관리하는 방식인 쿠키/세션과 달리, JWT는 단순히 데이터를 표현하는 형식

  • JWT로 만든 데이터를 브라우저로 보내도 쿠키처럼 자동으로 저장되지는 않지만, 변조가 거의 불가능하고 서버에 데이터를 저장하지 않기 때문에 서버를 stateless(무상태)로 관리할 수 있기 때문에 최근 많이 쓰이는 기술중 하나
  • stateless(무상태)와 stateful(상태 보존)의 차이를 간단히 설명하자면,
    Node.js 서버가 언제든 죽었다 살아나도 똑같은 동작을 하면 Stateless
    반대로 서버가 죽었다 살아났을때 조금이라도 동작이 다른 경우 Stateful
  • 서버가 스스로 어떤 기억을 갖고 다른 결정을 하냐 마냐의 차이
  • 로그인 정보를 서버에 저장하게 되면 무조건 Stateful(상태 보존)

사용방법

오픈소스 라이브러리 이용

jsonwebtoken

프로젝트로 이용할 폴더를 생성하고, 모듈을 설치

npm init
npm i jsonwebtoken -S

원하는 JSON 데이터 암호화

  • 데이터를 암호화
    const jwt = require("jsonwebtoken");
    
    const token = jwt.sign({ myPayloadData: 1234 }, "mysecretkey");
    console.log(token);
    • 개발자인 우리가 담을 데이터는 Payload에 담김 jwt.io 에서도 아래처럼 데이터를 입력하면 인코딩 된 데이터를 볼 수 있음
  • 위처럼 코드를 작성하고 실행하면 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0fQ.6XFgtNglH9hIzz5y8jAcI0g5kDnlAvnTTbxKIcL2CHY
    이와 똑같은 데이터가 출력

복호화

  • 코드로 복호화해서 출력

    const jwt = require("jsonwebtoken");
    
    const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0fQ.6XFgtNglH9hIzz5y8jAcI0g5kDnlAvnTTbxKIcL2CHY";
    const decodedValue = jwt.decode(token);

    앞서 말했듯이 JWT는 누구나 복호화가 가능
    그러나 검증을 통해 변조가 되지 않은 데이터인지 확인 가능

  • 복호화가 아닌, 변조되지 않은 데이터인지 검증

    const jwt = require("jsonwebtoken");
    
    const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJteVBheWxvYWREYXRhIjoxMjM0fQ.6XFgtNglH9hIzz5y8jAcI0g5kDnlAvnTTbxKIcL2CHY";
    const decodedValue = jwt.verify(token, "myesecretkey");

    만약 변조된 코드라면 위의 코드에서 에러가 발생

  • jwt.io 에서 복호화하여 확인가능

사용 환경

  • 보통 암호화 된 데이터는 클라이언트(브라우저)가 전달받아 다양한 수단(쿠키, 로컬스토리지 등)을 통해 저장하여 API 서버에 요청을 할 때 서버가 요구하는 HTTP 인증 양식에 맞게 보내주어 인증을 시도
  • 비유하자면, 놀이공원의 자유이용권과 비슷한 기능
    • 회원가입: 회원권 구매
    • 로그인: 회원권으로 놀이공원 입장
    • 로그인 확인: 놀이기구 탑승 전마다 유효한 회원권인지 확인
    • 내 정보 조회: 내 회원권이 목에 잘 걸려 있는지 확인하고, 내 이름과 사진, 바코드 확인
post-custom-banner

0개의 댓글