JWT(Json Web Token)은 왜 사용될까

송예인·2021년 5월 25일
4

Springboot+JPA

목록 보기
3/4

웹서버는 Stateless프로토콜인 HTTP를 사용하기 때문에 웹사이트에서 인증을 관리하기 위한 방안이 필요하다.
그렇기 때문에 웹 사이트는 일반적으로 유저의 접속 정보를 관리하기 위한 몇가지 방안을 사용한다.

Session 기반 인증

동작과정

1. 유저가 로그인을 한다.
2. 서버에서 계정정보를 읽어 사용자를 확인후, 사용자의 고유한 ID를 부여하여 세션 저장소에 저장후 세션 Id발행한다.
2. 유저는 해당 session Id를 받아 쿠키에 저장.
3. 인증이 필요한 요청마다 쿠키를 헤더에 실어 보낸다.
4. 서버는 클라이언트가 보낸 Session Id와 서버 메모리로 관리하고 있는 Session Id를 비교하며 Verification 수행한다.

장점

  • 구현이 명확하고 실제 서버에서 로그인 상태 확인이 유용하다.
  • 상대적으로 안전하다. 서버측에서 관리하기 때문에 클라이언트는 변조에 영향받거나 Stale(손상) 우려가 없다.(쿠키는 세션 저장소에 담긴 유저 정보를 얻기 위한 열쇠이므로 유의미한 정보가 아님)
    단점
  • 유저들의 세션에 대한 정보를 서버 메모리에 들고 있게 된다는 부담이 있다.
  • 서버 메모리에 세션 정보가 저장되기 때문에 Scale Out/Scale in 이 부담이 될 수 있으며, 결국에는 유저 상태에 무관하게 동작할 수 있는 Data-Driven 아키텍처가 요구된다.
  • 멀티 디바이스 환경에서 로그인 시 신경써줘야할 부분들이 생긴다.
  • 쿠키를 탈취당하더라도 안전하지만, 해커가 그 쿠키를 사용해 사용자인 척 http 요청을 보내면 서버의 세션 저장소에서는 사용자로 오인해 정보를 잘못 뿌려줄 수 있음
    - https를 사용하여 요청 자체를 탈취해도 안의 정보를 읽기 힘들게 하기
    • 세션에 유효시간을 넣어 주기

토큰 기반 인증 방식

  • 인증에 필요한 정보들을 암호화 시킨 토큰을 뜻함
  • 위의 세션/쿠키 방식과 유사하게 사용자는 Access Token을 HTTP 헤더에 실어 서버로 보냄

  • 토큰을 만들기 위해서 크게 3가지 필요
  1. Header: 위 3가지 정보를 암호화 할 방식(alg), 타입(type)
  2. payload: 서버에서 보낼 데이터 들어감. 일반적으로 유저의 고유 ID값, 유효기간 들어감
  3. Verify Signature: Base64방식으로 인코딩한 Header,payload 그리고 SECRET KEY를 더한 후 서명된다.

최종적인 결과 : Encoded Header + "." + Encoded Payload + "." + Verify Signature

Header, Payload -> 인코딩될 뿐(16진수로 변경), 따로 암호화되지 않습니다. 따라서 JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있습니다. 여기서 누구나 디코딩할 수 있다는 말은 Payload에는 유저의 중요한 정보(비밀번호)가 들어가면 쉽게 노출될 수 있다는 말이 됩니다.

Verify Signature -> SECRET KEY를 알지 못하면 복호화할 수 없습니다. A 사용자가 토큰을 조작하여 B 사용자의 데이터를 훔쳐보고 싶다고 가정하겠습니다. 그래서 payload에 있던 A의 ID를 B의 ID로 바꿔서 다시 인코딩한 후 토큰을 서버로 보냈습니다. 그러면 서버는 처음에 암호화된 Verify Signature를 검사하게 됩니다. 여기서 Payload는 B사용자의 정보가 들어가 있으나 Verify Signature는 A의 Payload를 기반으로 암호화되었기 때문에 유효하지 않는 토큰으로 간주하게 됩니다. 여기서 A사용자는 SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없다는 걸 확인할 수 있습니다.

동작과정

1. 사용자가 로그인을 한다.
2. 서버에서는 계정정보를 읽어 사용자를 확인 후, 사용자의 고유한 ID값을 부여한 후, 기타 정보와 함께 Payload에 넣습니다.
3. JWT 토큰의 유효기간을 설정합니다.
4. 암호화할 SECRET KEY를 이용해 ACCESS TOKEN을 발급합니다.
5. 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보냅니다.
6. 서버에서는 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후, 조작 여부, 유효기간을 확인합니다.
7. 검증이 완료된다면, Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져옵니다.

세션방식과의 차이점
세션/쿠키 방식은 세션/쿠키 저장소에 유저의 정보를 넣는 반면, JWT는 토큰 안에 유저의 정보들을 넣는다. 클라이언트 입장에서는 http헤더에 세션id나 토큰을 실어 보내준다는 점에서 동일하나, 서버 측에서는 인증을 위해 암호화를 하냐(JWT), 별도의 저장소를 이용하냐는 차이가 발생(세션)

장점

  • 간편합니다. 세션/쿠키는 별도의 저장소의 관리가 필요합니다. 그러나 JWT는 발급한 후 검증만 하면 되기 때문에 추가 저장소가 필요 없습니다. 이는 Stateless 한 서버를 만드는 입장에서는 큰 강점입니다. 여기서 Stateless는 어떠한 별도의 저장소도 사용하지 않는, 즉 상태를 저장하지 않는 것을 의미합니다. 이는 서버를 확장하거나 유지,보수하는데 유리합니다.

  • 확장성이 뛰어납니다. 토큰 기반으로 하는 다른 인증 시스템에 접근이 가능합니다. 예를 들어 Facebook 로그인, Google 로그인 등은 모두 토큰을 기반으로 인증을 합니다. 이에 선택적으로 이름이나 이메일 등을 받을 수 있는 권한도 받을 수 있습니다.

단점

  • 이미 발급된 JWT에 대해서는 돌이킬 수 없습니다. 세션/쿠키의 경우 만일 쿠키가 악의적으로 이용된다면, 해당하는 세션을 지워버리면 됩니다. 하지만 JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능합니다. 따라서 악의적인 사용자는 유효기간이 지나기 전까지 신나게 정보들을 털어갈 수 있습니다.
    - 기존의 Access Token의 유효기간을 짧게 하고 Refresh Token이라는 새로운 토큰을 발급합니다. 그렇게 되면 Access Token을 탈취당해도 상대적으로 피해를 줄일 수 있습니다.

  • Payload 정보가 제한적입니다. 위에서 언급했다시피 Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있습니다. (세션/쿠키 방식에서는 유저의 정보가 전부 서버의 저장소에 안전하게 보관됩니다) 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없습니다.

  • JWT의 길이입니다. 세션/쿠키 방식에 비해 JWT의 길이는 깁니다. 따라서 인증이 필요한 요청이 많아질 수록 서버의 자원낭비가 발생하게 됩니다.

0개의 댓글