유튜브 알고리즘에 뜬 영상을 보다가 코딩애플님의 JWT 영상을 보고 구조와 취약점에 대해 좀 더 자세히 공부해보았다. 항해99에서 가르쳐준 대로만 적용을 했기 때문에 별 고민 없이 사용했는데 보안쪽으로 중요한 요소라 좀 더 공부를 해봐야 할 것 같다.
Json Web Token. 유저를 인증하고 식별하기 위한 토큰 기반 인증.
토큰 자체에 사용자의 권한 정보나 서비스 정보가 포함된다.
RESTful과 같은 Stateless 환경에서 사용자 데이터를 주고받을 수 있다.
{
"typ": "JWT",
"alg": "HS256"
}
iss : 토큰발급자
sub : 토큰 제목
aud : 토큰 대상자
exp : 토큰 만료 시간
nbf : 토큰 활성 날짜 (이 이전 토큰은 활성화되지 않음을 보장한다)
iat : 토큰 발급 시간
jti : 토큰 식별자 (issuer가 여러명일때 구분을 위함)
가장 중요한 것은 민감한 정보는 담지 않아야 한다.
특별한 암호화가 되어있지 않기 때문에 누구나 디코딩이 가능해 payload에 담긴 내용을 볼 수 있다. 그러므로 단순 식별 정보만 담아야 한다.
출처는 코딩애플
일단 JWT 토큰은 쿠키-세션에 비해 가지고 있는 정보다 많다. 세션은 세션 저장소에서 세션ID로 클라이언트의 정보를 계속 찾아봐야 하는데 JWT는 토큰만 있으면 통과를 시켜준다. 그래서 이용자가 많으면 JWT가 성능에서 유리하다.
하지만 이런 점 때문에 JWT는 여러 취약점이 존재한다.
JWT 토큰은 디코딩이 쉬우니 개인정보를 최소한만 담고 있게 해야한다.
alg(암호화 알고리즘)을 HS256을 쓰는 것이 일반적이지만 none으로 만들게 될 경우 취약점이 발생한다. 가끔 none으로 공격이 들어오니 이때 거절을 할 수 있게 해야한다.
시크릿키를 짧고 간단한 문자열로 만들면 안된다.
키를 매우 길게 쓰고 공유를 금지하던가, 생성용키/검증용키 2개로 나눠서 쓰면 좋다.
JWT는 누가 중간에 탈취해도 stateless하기 때문에 구조상 탈취된 토큰을 정지할 수 없다.
탈취하기 어려운 저장소(httpOnly cookie)에 저장해 훔치기 어렵게 하거나
JWT 유효기간을 5분정도로 매우 짧게 만들면 된다.
Refresh Token을 쓰면 토큰의 유효기간을 짧게 만들어서 자주 발급하게하는게 가능하다.
Refresh Token Rotation(Refresh Token을 1회용으로 만듬)을 활용한다.
더 자세한 내용은 추후 Refresh Token에 대해서 정리해보려한다.