Json Web Token

이연중·2021년 6월 28일
0

Node.js

목록 보기
14/14

전자 서명된 URL-safe의 JSON

서버와 클라이언트 간 정보를 주고 받을 때 헤더에 포함된 JWT 정보를 통해 인증

서버 인증 방식과 토큰 인증 방식


  • 서버 인증 방식(Cookie, Session): 기존 인증 시스템은 서버 기반 인증 방식으로 서버 측에서 사용자들의 정보를 기억하고 있어야 했다. 이를 위해 세션을 유지해야 하는데, 메모리, 디스크, DB 등을 통해 관리했었다.(stateful)

  • 토큰 인증 방식: 인증받은 사용자들에게 토큰을 발급하고 서버에 요청했을 때, 헤더에 토큰을 보내 유효성 검사를 한다. 더이상 사용자의 인증 정보를 서버나 세션에 유지하지 않고 클라이언트에서 들어오는 요청만으로 작업을 처리한다.(stateless)

장단점


장점

  • stateless 적합
  • scalability: 서버 기반 인증 시스템에 비해 서버의 확장성이 높음
  • 보안성: 세션 인증을 쿠키 전달이 필요 없으므로 보안성 향상
  • extensibility
  • CORS: 어떤 디바이스, 도메인에서도 토큰이 유효하면 정상처리
  • 다양한 환경과 언어 지원

단점

  • 클라이언트에 토큰이 저장되므로, DB에서 사용자 정보를 조작하더라도 토큰에 직접 적용 불가하며 토큰을 새로 발행해야 함
  • 서비스가 커지면 토큰이 필요로 하는 데이터가 커져 토큰이 커지고 이에 따라 HTTP 요청의 트래픽 양에 영향을 미침
  • 헤더와 페이로드가 Base64로 인코딩 되어있기에 클라이언트에 있는 토큰 내부 정보 노출

JWT 토큰 구성


JWT는 헤더, 페이로드, 서명으로 구성되며, 각각은 점으로 구분한다.

  • header: 토큰 타입(토큰의 유형 JWT)과 해시 암호화 알고리즘(HMAC, SHA256, RSA 등) 정보. 헤더 파트가 base64로 인코딩 되어 첫 번째 파트에 들어가게 됨

    • {
          "typ":"JWT",
          "alg":"HS256"
      }
  • payload: 토큰에 담을 클레임(정보의 한 조각) 정보 포함. 클레임은 name/value의 한 쌍으로 이루어져 있음

    • 등록된 클레임(Register Claim): 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들이 담겨져 있음

      • iss: 토큰 발급자
      • sub: 토큰 제목
      • aud: 토큰 대상자
      • exp: 토큰 만료시간
      • nbf: 토큰 활성 시간
      • iat: 토큰 발급 시간
      • jti: JWT의 고유 식별자로 중복처리를 방지하기 위해 사용(일회용 토큰 사용시 유용)
    • 공개 클레임(Public Claim): 공개 클레임들은 충돌 방지된 이름을 가지고 있어야 함. 이를 위해 클레임 이름을 URI 형식으로 지음

      • {
            "http://alwaysLee.com/jwt_claims/is_auth": true
        }
    • 비공개 클레임(Private Claim): 등록된 클레임도 아니고 공개된 클레임도 아닌 것. 클라이언트와 서버 간 협의하에 사용되는 클레임 이름들. 중복 사용 가능하는 유의할 것

      • {
            "userName":"alwaysLee"
        }
  • signature: secret key를 포함해 암호화 되어있음(헤더의 인코딩 값과 정보의 인코딩 값을 합친 후 주어진 비밀키로 해싱하여 생성).

    • //HMAC SHA256 알고리즘을 사용한다 가정
      HMACSHA256(
        base64UrlEncode(header) + "." +
        base64UrlEncode(payload),
        secret)
    • 이를 통해, 메시지가 중간에 변경되지 않았음을 검증하며, JWT를 보낸 사람이 신뢰할 수 있는 대상인 것도 알 수 있음

  • 최종적으로, 아래와 같은 Base64로 인코딩 된 문자열이 3개가 나옴

Node Js에서의 사용


발급

const jwt = require('jsonwebtoken');
const token = jwt.sign({ foo: 'bar' }, 'secret-key', { expiresIn: '7d' }, (err, token) => {
    if(err) {
        console.log(err);
        return;
    }
    console.log(token);
});

검증

const jwt = require('jsonwebtoken');

module.exports.check= (token)=>{
    let check
    try{
        check= jwt.verify(token,'secret-key')
    }catch(err){
        console.log(err)
    }
    return check
}

참고

https://jwt.io/

https://www.freecodecamp.org/news/securing-node-js-restful-apis-with-json-web-tokens-9f811a92bb52/

profile
Always's Archives

0개의 댓글