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 통신 과정
- 클라이언트에서 사용자, 아이디, 패스워드를 서버로 요청
- 서버는 파라미터를 DB에서 조회, 사용자를 인증하고, 토큰을 발급
- 토큰을 응답으로 전달
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