Web/Spring

세션 vs 토큰, JWT 구조와 취약점

TLdkt 2022. 10. 11. 18:18
728x90
반응형

🚀들어가며

 프로젝트에서 성적 정보 등을 다루다 보니 페이지 조회 권한을 어떻게 설정할 것인지, 우리가 채택한 시큐리티 방식에는 어떤 장단점이 있는지 고민하게 됐다. 사용자 경험을 중시하는 서비스의 경우 주로 토큰 방식을 쓰는 것 같지만, 애매한 민감정보(?)를 다루는 경우 어떤 식으로 현업에서는 대책을 내고 있는지도 궁금해졌다.

그중에서도 우선은 최근 가장 보편적으로 쓰이는 토큰 방식인 JWT에 대해 정리해보려 한다. 

 

 

1. JWT란?

  • Json Web Token
  • JSON포맷 토큰 정보 인코딩→ Secret Key로 서명한 메세지→Web Token으로 활용

2. JWT 종류

2.1. Access Token

  • 보호된 정보 접근용 권한 부여
  • 보호된 정보: 사용자 이메일, 연락처, 사진 등
  • 로그인 시 access, refresh 모두 받지만, 권한 획득을 위해 실질적으로 사용
  • 비교적 짧은 유효기간

2.2. Refresh Token

  • Access token을 새로 발급받기 위한 토큰
  • 다시 로그인 인증할 필요 없어짐
  • 문제: 악의적 사용자가 refresh token 탈취 시 막을 방법 X

3. JWT 구조

3.1. Header

  • 어떤 종류의 토큰인지(ex: JWT)
  • 어떤 알고리즘으로 Sign할지(ex: base64방식 인코딩)
{
  "alg": "HS256",
  "typ": "JWT"
}

예시 Json 객체

→base64방식 인코딩

→JWT 헤더 완성!

3.2. Payload

  • 사용자 정보
  • 접근권한, 사용자 데이터 등
  • signature를 통해 유효성 검증될 것
  • 민감정보 XXX
{
  "sub": "someInformation",
  "name": "phillip",
  "iat": 151623391
}

예시 Json 객체

→base64방식 인코딩

→JWT 페이로드 완성!

3.3. Signature

  • 비밀키+알고리즘(헤더의)→단방향 암호화 수행
  • 토큰 위변조 유무 검증용
  • salt 추가해 암호화
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);

4. JWT 사용 예시: 권한 부여⭐

Gmail 연동되어 이메일 읽어와야 하는 애플리케이션

  1. Gmail 인증서버에 로그인 정보 제공
  2. 인증 성공 시 JWT 발급받음
  3. 앱: 받은 JWT로 사용자의 이메일 읽어오기 가능

5. JWT 토큰 기반 인증 절차

  1. 클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청
  2. 아이디/비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 암호화 된 토큰을 생성
    • Access Token과 Refresh Token을 모두 생성
      • 토큰에 담길 정보(Payload)는 사용자를 식별할 정보, 사용자의 권한 정보 등
      • Refresh Token 이용해 새로운 Access Token을 생성할 것이므로 두 종류의 토큰이 같은 정보를 담을 필요없음

  3. 토큰을 클라이언트에게 전송하면, 클라이언트는 토큰을 저장
    • 저장하는 위치는 Local Storage, Session Storage, Cookie 

  4. 클라이언트가 HTTP Header(Authorization Header) 또는 쿠키에 토큰을 담아 request를 전송
  5. 서버는 토큰을 검증하여 "아 우리가 발급해 준 토큰이 맞네!"라는 판단이 될 경우, 클라이언트의 요청을 처리한 후 응답을 보냄

 

 

6. 세션 VS  토큰

세션 기반 자격증명의 배경

  • http 프로토콜: 비연결성(Connectionless) , 비상태성(Stateless)

→로그인 인증이 성공적이더라도 매번 request마다 인증된 사용자인지 알기 어려움

→사용자의 인증 성공 시 request 상태 유지 필요

→세션 등장

 

  • 서버 측에서
    • 세션 저장소 속 세션 정보와
    • 사용자 제공 정보 일치 여부 확인

 

세션 기반 자격 증명 특징

  • 서버 측 세션 저장소에서 인증정보 관리
    • 서버에서 관리=보안 유리
    • 데이터가 많아질수록 서버 부담
  • 세션 ID는 클라이언트 쿠키에 저장
    • request 전송 시 증명 수단으로 사용됨
  • 세션 ID 하나만 클라이언트에서 사용
    • 상대적으로 네트워크 트래픽 부담 적음
  • 서버 확장→세션 불일치 문제 발생 가능성 높아짐
  • Sticky Session, Session Clustering, Session저장소 외부 분리 등으로 보완
  • SSR 방식의 애플리케이션에 적합

 

 

토큰 개념 이해

  • 출입 카드와 유사(신원정보 기재, 권한 부여됨)
  • 토큰(인증정보, 토큰별 접근권한)

토큰 기반 자격 증명 특징

  • 클라이언트의 관리
    • 보안 상대적 불리
    • 상태유지 X =확장성 유리
  • request 헤더에 토큰 포함
  • 토큰 속에 인증된 사용자 정보(이름, 나이, 어쩌구저쩌구)

→ 상대적으로 많은 네트워크 트래픽 사용

  • 토큰 속 사용자 정보는 암호화X
  • 토큰 만료 전까지 무효화 불가능

세션vs 토큰 증명 비교

항목
세션
토큰
클라이언트의 관리대상
Session Id
Token(+Credential)
사용자 정보 관리 장소
Server
Client
보안성
유리
불리
확장성
불리(Session 불일치)
유리
트래픽 사용량
작음
자격증명 방법
DB의 credential과 대조
header에 포함해 전송
무상태성
X
O
무효화 방법
-
토큰 무효화 설정 필요

✨나가며

jwt의 경우 확실히 서버 부담이 줄고, 확장성이 좋지만 그만큼 보안에 태생적인 한계가 있다. 처음 배울 때는 막연한 느낌이었는데, 막상 구현할 때가 되니 고민할 지점이 많은 방식 같다. 

정리해보면 이 정도 이슈가 있는 듯한데... 어떤 식으로 보완할 수 있고, 현업에서는 어떻게 해결하는지 추후 포스팅해봐야겠다!

 

JWT 사용 시 고려할 점 

1. None Hashing Algorithm 

2. Token Sidejacking 

3. No Bulit-In Token Revocation by the User

4. Token Information Disclosure 

5. Token Storage on Client Side

6. Weak Token Secret 

728x90
반응형