JWT 란?

JWT 이론

JWT(json web token)란?

JWT는 사용자를 인증할 때 사용하는 방식중 하나로 세션과 달리 클라이언트에 토큰 값을 저장하고, 이 값을 요청 시에 서버로 보내 인증을 하는 구조이다. 서버에 세션을 저장하는 것이 아니라 토큰이 전달될때 확인만 하는 구조이기 때문에 서버가 분산된 시스템에서는 처리하기 좋다.


당연하게도 json 형식이고 구성은 다음과 같이 이루어진다.

  • Header
  • Payload
  • Signature

Header에는 토크 타입이나, 암호화에 사용하는 알고리즘을 정의한다.

{
	"typ": "JWT",
	"alg": "SHA256"
}

Payload에는 유저 정보를 담는데, 간단히 정리하면 다음과 같다.

{
	"sub": "인증 주체",
	"iss": "발급처",
	"iat": "발급 시각",
	"exp": "만료 시긱",
	"aud": "클라이언트"
}

Signature에는 해당 토큰이 서버에서 생성한 것인지 확인 할때 중요한 부분인데, 헤더+페이로드를 서버의 secret_key로 서명한다. 또는 base64+payload+secret_key 로 서명하기도 한다. (당연한 이야기 지만, secret_key가 변경되면 해당 값도 달라지기 때문에 서비스 도중에 변경하게 되면 이슈가 있을 수 있다.)


JWT 통신 과정

  1. 클라이언트에서 사용자, 아이디, 패스워드를 서버로 요청
  2. 서버는 파라미터를 DB에서 조회, 사용자를 인증하고, 토큰을 발급
  3. 토큰을 응답으로 전달


JWT의 문제점?

JWT의 문제점으로는… 담는 정보가 많을 수록 토큰 길이도 커진다는 점과 클라이언트에 토큰을 저장하기 때문에 이 토큰이 탈취될 수 있다는 점이다. 이 점을 보완하기 위해 탈취 되더라도 재발급 할 수 있도록, 토큰을 access token 과 refresh token으로 나누는 방식으로 활용한다. access_token(인증할 때 사용하는 토큰)의 expire을 짧게 가져가서 일정 시간마다 갱신되게 하는 것이다.


토큰은 어디에 저장하나?

우선 토큰을 브라우저에 저장 시켜야 한다. 그래야 사용자가 일일이 로그인하는 수고를 덜할 수 있는데… 문제는 저장 위치이다. 2가지 옵션이 있는데, 하나는 local_storage 이고 다른 하나는 쿠키이다. 하지만, 둘다 JS를 통해서 글로벌 변수로 선언해서 가져올 수 있다. 토큰이 탈취된다면, XSS 나 CSRF 공격이 들어올 수 있다. 관련된 공격으로는 아래와 같다.


관련된 공격

XSS(Cross Site Scripting)

XSS 는 사이트 내에 악의적인 코드를 심어두어서 사용자의 개인 정보나 서버 접근 등의 공격을 하는 것을 의미한다. 웹 페이지를 수정해서 다른 사용자가 접속 했을 때 피싱서버로 리다이렉션 시킨다던지 여러 방식으로 활용한다.


CSRF(Cross Site Request Forgery)

사용자 정보를 이용해 공격자가 요청을 보내도록 하여 피해를 주는 공격을 의미한다. 예를 들면 비밀번호 변경 버튼의 주소를 변경해서 시 유저 아이디와 비밀번호를 보낼 때 다른 서버(공격자의 서버)로 요청하게 하는 방식이다.

위 2가지 방식 모두 Cross Site(사이트를 넘어서하는 공격), 공격자의 서버를 경유하게 두어서 개인정보를 수집할 수 있다는 문제가 있다.

그러면 어케…?

이를 방지하려면 쿠키에 저장하되, 조금 처리를 해주어야 한다. 그게 Secure, HttpOnly 쿠키이다.


HttpOnly 쿠키..?

기존 자바 스크립트 등에서 쿠키를 조회하고 탐색할 수 있는데, 해커 등 악의적인 목적으로 쿠키를 탈취(XSS : Cross Site Scripting) 할 수 있기 때문에 문제가 되었다. 이를 막기 위해 해당 옵션으로 브라우저에서 쿠키에 접근할 수 없도록 제한하는 것이 HttpOnly 쿠키이다.

# 아래처럼 끝에 HttpOnly를 붙이면 된다.
Set-Cookie: 쿠키이름=; path=/; HttpOnly


이는 JWT 뿐만아니라 기존 브라우저 내에 쿠키에 접근할 일이 별로 없기 때문에 필수적으로 붙여두는 게 좋다. 웹 보안의 일부라고 생각하면 될 것 같다. 물론 패킷 스니핑은 별도로 막아야 한다.(와이어 샤크 등으로 전송 레이어에서 패킷을 분석하는 방식)

네트워크에서 패킷을 가로채는… 스니핑은 어떻게…?


이 경우 secure 쿠키를 이용하면 된다. secure 쿠키의 경우, HTTPS 가 아닌 통신으로는 쿠키를 보내지 않는 다는 것이다. (HTTPS 은 SSL/TLS 방식이 적용 되었기 때문에 통신 과정에서도 암호화가 되기 때문이다.) 주로 세션 쿠키에 설정된다.

Set-Cookie: 쿠키이름=; path=/; secure