Published on

OAuth2 Login + JWT (1) JWT는 무엇일까

Authors
  • avatar
    Name
    ywj9811
    Twitter

JWT (Json Web Token)

우선 세션에 대해서 살펴보도록 하자

만약 Web 브라우저에서 서버로 요청을 하면 서버에서 반환을 한다.

반환 할 때 header의 쿠키에 세션ID를 담아주게 된다.

최초 요청시 세션ID를 생성해서 담아준다.

이후에는 요청시에 세션ID를 보내주고 이전에 생성한 ID와 비교 후 응답에도 그대로 돌려주는 것이다.

  1. 최초 요청 : 세션 ID없이 요청
  2. 최초 응답 : 세션 ID 생성 & 쿠키에 담아서 응답, 세션 목록에 저장
  3. 이후 요청 : 세션 ID와 함께 요청
  4. 이후 응답 : 기존의 세션ID와 비교 후 일치하면 그대로 담아서 응답

이 세션은 언제 사라지게 될 것인가

  • 서버를 종료
  • 사용자 브라우저를 종료
  • 특정 시간이 지나게 되면 서버에서 사라지게 됨

세션의 단점

만약 동접자 수가 굉장히 많게 된다면 여러개의 서버를 만들게 된다.

따라서 1번 서버, 2번 서버, 3번 서버가 있다.

이 때 클라이언트가 처음 로그인 할 때 1번 서버에서 요청을 하여 1번 서버의 세션저장소에 세션ID가 저장되어 있다.

만약, 1번 서버가 부하가 되어 2번 서버로 요청하게 되면 2번 서버에서는 해당 ID가 없기 때문에 요청이 받아지지 않을 것이다.

이런 문제는 발생하면 안된다.

그래서 1번 서버에 고정으로 요청하게 설정하거나 DB에 모든 세션값을 저장하거나 할 수 있다.

하지만 이런 과정은 굉장히 복잡하고 느려질 수 있다. RAM이 아닌 HDD에 접근하게 되기 때문이다.

해결책

위와 같은 경우를 해결하기 위해서 세션값을 저장하기 위한 서버를 하나 더 파게 된다.

이 때 이 서버는 메모리를 가지고 있는 서버로 IO가 일어나지 않아야 한다.

→ 보통 Redis라는 서버를 사용한다.


해결책 2

JWT를 사용하면 세션의 고질적인 문제점을 해결할 수 있다.

  • 웹은 TCP 방식으로 통신함 (연결 지향적 & 신뢰성)
  • 하지만 중간에 낚아채지면 안됨 (유출 되면 안됨)
    • 누구로 부터 전달을 받는지 또한 알 수 있어야 함 (인증 문제)

참고

RSA 암호

  • public key : 공개 키 (공개해도 상관없는 키)
  • private key : 개인 키

: 공개 키와 개인 키를 통한 암호화


공개 키 기반 암호화

A ———메시지———> B

해커

A가 공개 키(B의 공개키) 로 B에게 전달을 함

B는 이를 받으면 자신의 개인 키를 이용하여 메시지를 확인함 (공개 키로 전달 받아서 개인 키로 열어보는 것임)

: 중간에 해커가 가로채도 B의 개인 키가 없기 때문에 확인하지 못함.

이를 통해서 유출 위험 해결


개인 키 기반 전자 서명

A ———메시지———> B

해커

A가 개인 키(A의 개인 키) 로 B에게 전달을 함

B는 이를 받아서 A의 공개 키로 메시지를 확인함 (개인 키로 전달 받으면 공개 키로 확인)

: 이는 A가 보냈음을 보증함.

이를 통해서 인증 문제 해결


위 두가지 융합

A ———메시지———> B

해커

A가 B의 공개 키로 데이터를 암호화 하고 A 자신의 개인 키로 한번 더 감싸준다.

: B의 공개 키를 통해 암호화를 하고 A 자신의 개인 키로 자신이 보냈음을 보증한다.

B는 이를 받으면

  1. A의 공개 키를 통해 열어 봄
    1. 만약 열리지 않는다면 중간에 변조된 것으로 폐기
    2. 열린다면 다음으로 진행
  2. B의 개인 키로 열어 봄
  3. 확인 완료

JWT는 RSA를 통한 암호화를 한다.

RFC 문서

RFC(Request for Comments) 문서"의견을 요청하는 문서"라는 의미로, 국제 인터넷 표준화 기구(IETF; Internet Engineering Task Force)에서 관리하는 기술 표준이다.

콘텐츠에 대해 특별한 제한은 없지만 주로 프로토콜(protocol) 및 파일 형식등이 주요 주제이며 승인된 문서는 유일한 일련 번호를 갖게 되며 "RFC-일련번호" 형식으로 불린다.

이렇게 정식으로 일련 번호가 부여된 RFC 문서는 변경되거나 폐지되지 않는다.

만약 변화하는 환경에 맞게 프로토콜이 업그레이드되어 기술 표준을 갱신할 경우 RFC 는 명확성을 위해 기존 문서를 갱신하는게 아니라 새로운 RFC 를 만들고 이로 인해 어떤 문서가 무효화되었는지 표시한다.

RFC 문서의 대표적인 예로 RFC 2616 이 있다.

이는 HTTP/1.1 에 대한 문서이다.

해당 문서를 살펴보면 이 문서로 인해 무효화된 문서는 RFC 몇 번 문서인지, 혹은 이 문서를 무효화 시키는 생성된 새로운 문서는 무엇인지 표시해주고 있다.

JWT는 RFC 7519번 문서에서 다루고 있다.

JWT의 구조

  • Header
    {
    	"alg": "HS256"
    	"typ": "JWT"
    }
    
  • Payload (정보)
    • 등록된 클레임
      • iss(발행자)
      • exp(만료 시간)
      • sub(주제)
      • aud(청중)
      • 등등 (위 정보를 넣는 것이 필수는 아님)
    • 개인 클레임
      • userId 등등의 우리가 원하는 정보
    {
    	"sub": "12345678"
    	"name": "John Deo"
    	//여기까지 등록된 클레임
    	"admin": true
    	//이 부분은 개인 클레임
    }
    
    위의 값들은 Base64Url로 인코딩 된다.
  • Signature (서명)
    • Header, Payload, 그리고 나의 개인 키를 넣어주게 된다.
    HMACSH256(
    	base64UrlEncode(header) + "."
    	base64UrlEncode(payload),
    	secret
    )
    

이렇게 이루어져 있다.

이렇게 만들어진 JWT는 아래와 같은 모양을 가진다.

jwt1

Header(빨강), Payload(보라), Signature(위 값들 + Secret)(파랑) 으로 나오게 된다.

즉, 서버는 JWT를 받으면 Secret가 일치하는지 확인하고 일치한다면 인증으로 처리하게 되는 것이다.

따라서 1번 2번 3번 서버가 있어도 Secret값만 알고 있다면 이전 세션과 다르게 문제 없이 처리할 수 있다.