[보안] JWT, CSRF

JWT

JWT는 공개키 / 비밀키 기술을 사용하여 서명한다.

JWT는 3가지 부분으로 구성된다.

header.payload.signature 의 모양

이해하기

토큰에 대해서 이해하기 위해서, 인증서버와 api서버가 분리되어 있는 경우를 가정해보자.

JWT를 생성할때는 비밀키를 사용하여, (헤더 + 페이로드)를 서명한다. 토큰에 대한 서명은 비밀키를 가진 인증 서버가 할 수 있는데, 이 서명에 대한 검증은 공개키를 가진 누구나 할 수 있다.

토큰은 누구나 디코딩 할 수 있는데, 이 토큰이 안전할까?

JWT 토큰 자체는 암호화(encryption) 된 것이 아니라 인코딩(encoded) 되어 있는 것이다. 따라서 토큰의 내용은 그냥 decode가 가능하다. 그렇기 때문에, jwt를 만들때는 내부에 민감한 정보를 사용하지 않는 것이 좋다.

그렇다면, 이 토큰을 통해서 인증을 한다던가 하는 작업을 해도 괜찮은걸까?

인증서버에서 비밀키로 서명을 해서 토큰을 만들 경우, api 서버에서 해당 토큰을
공개키를 통해서 서명을 검증할 수 있다.

인증서버와 api 서버가 각각 비밀키, 공개키를 가지고 이를 암호화 복호화하는데, 즉, 비밀키를 알지 못하면 토큰에 자체를 변조할 수 없게 된다. 그렇기 때문에 중간에 누군가 토큰을 탈취하여 내용을 변경한다고 하여도, 비밀키를 모르기 때문에 임의로 토큰의 내용을 변경한다고 하여도, 공개키로 이를 검증할 수 없게 된다.

CSRF(crosse site request forgery) 문제점?

탈취하여도 토큰의 내용은 변경할 수 없다고 하였다고 보안상 안전한 것일까?

누군가 클라이언트의 토큰을 탈취하여, api 서버로 요청을 보내서 민감한 정보를 가져온다면 어떻게 될 것인가?

CSRF 해결책

이러한 문제 때문에 토큰은 2가지를 발행하는 것이 좋다.

Access Token은 일반적으로 15분에서 12시간 정도의 생명주기를 가지고, Refresh Token은 1~2달 정도의 유효기간을 가진다.

  1. 클라이언트에서 로그인. /login 으로 요청
  2. 서버에서 리프레시 토큰 체크 2.1 리프레시 토큰있으면 리프레시 토큰 쿠키로 전달 및 엑세스 토큰 발급 2.2 리프리세 토큰이 없으면 리프레시 토큰 생성 후 2.1 과정
  3. 엑세스 토큰으로 계속 api 서버 접근
  4. 엑세스 토큰이 만약 만료되면 4xx (상태코드 정해서) 에러를 발생
  5. 리프레시 토큰으로 재요청 -> 엑세스 토큰 발급 5.1 리프레시 토큰 만료시 401 상태코드를 통해 unauthroize를 알림 5.2 이 경우, 로그인 화면으로 리다이렉트

#로그인#