JWT
JWT는 공개키 / 비밀키 기술을 사용하여 서명한다.
JWT는 3가지 부분으로 구성된다.
header.payload.signature
의 모양
- 헤더 - 서명시 사용되는 알고리즘, 키에 대한 식별자 (인코딩)
- 페이로드 - (인코딩)
- 시그니처 - (헤더 + 페이로드)를 합친 문자열을 서명한 값
이해하기
토큰에 대해서 이해하기 위해서, 인증서버와 api서버가 분리되어 있는 경우를 가정해보자.
JWT를 생성할때는 비밀키
를 사용하여, (헤더 + 페이로드)를 서명한다.
토큰에 대한 서명은 비밀키를 가진 인증 서버
가 할 수 있는데, 이 서명에 대한 검증은 공개키를 가진 누구나 할 수 있다.
- 인증 서버에서 토큰을 (비밀키를 통해 서명후) 발행한다.
- 클라이언트가 해당 토큰을 가지고 api 서버에 접근한다.
- api 서버는 공개키를 통해서 해당 서명을 검증할 수 있다.
토큰은 누구나 디코딩 할 수 있는데, 이 토큰이 안전할까?
JWT 토큰 자체는 암호화(encryption) 된 것이 아니라 인코딩(encoded) 되어 있는 것이다. 따라서 토큰의 내용은 그냥 decode가 가능하다. 그렇기 때문에, jwt를 만들때는 내부에 민감한 정보를 사용하지 않는 것이 좋다.
그렇다면, 이 토큰을 통해서 인증을 한다던가 하는 작업을 해도 괜찮은걸까?
인증서버에서 비밀키로 서명을 해서 토큰을 만들 경우, api 서버에서 해당 토큰을
공개키
를 통해서 서명을 검증할 수 있다.
- 비밀키로 암호화 (서명, 시그니처) -> 공개키로 복호화
인증서버와 api 서버가 각각 비밀키, 공개키를 가지고 이를 암호화 복호화하는데, 즉, 비밀키를 알지 못하면 토큰에 자체를 변조할 수 없게 된다. 그렇기 때문에 중간에 누군가 토큰을 탈취하여 내용을 변경한다고 하여도, 비밀키를 모르기 때문에 임의로 토큰의 내용을 변경한다고 하여도, 공개키로 이를 검증할 수 없게 된다.
CSRF(crosse site request forgery) 문제점?
탈취하여도 토큰의 내용은 변경할 수 없다고 하였다고 보안상 안전한 것일까?
누군가 클라이언트의 토큰을 탈취하여, api 서버로 요청을 보내서 민감한 정보를 가져온다면 어떻게 될 것인가?
CSRF 해결책
이러한 문제 때문에 토큰은 2가지를 발행하는 것이 좋다.
- access Token : 짧은 주기를 가진 토큰
- refresh Token: 엑세스 토큰 발급을 위한 토큰
Access Token은 일반적으로 15분에서 12시간 정도의 생명주기를 가지고, Refresh Token은 1~2달 정도의 유효기간을 가진다.
- 클라이언트에서 로그인. /login 으로 요청
- 서버에서 리프레시 토큰 체크 2.1 리프레시 토큰있으면 리프레시 토큰 쿠키로 전달 및 엑세스 토큰 발급 2.2 리프리세 토큰이 없으면 리프레시 토큰 생성 후 2.1 과정
- 엑세스 토큰으로 계속 api 서버 접근
- 엑세스 토큰이 만약 만료되면 4xx (상태코드 정해서) 에러를 발생
- 리프레시 토큰으로 재요청 -> 엑세스 토큰 발급 5.1 리프레시 토큰 만료시 401 상태코드를 통해 unauthroize를 알림 5.2 이 경우, 로그인 화면으로 리다이렉트
#로그인#