지난 글에서 인증과 인가의 개념에 대해 알아보았다. 이번엔 인증의 여러 방법(쿠키, 세션, 토큰) 중 토큰에 대해 알아보자.
토큰 기반 인증은 클라이언트가 서버에 접속을 하면 해당 클라이언트에게 인증되었다는 의미로 '토큰'을 부여한다.
->
이 토큰은 유일하며 토큰을 발급받은 클라이언트는 이후 서버에 요청을 보낼 때 헤더에 이 토큰을 담아 보낸다.
->
서버는 클라이언트에게 받은 토큰을 서버에서 발급해준 토큰과 일치한지 검사한다. 일치하면 인증 완료
로그인 과정을 예로 들면 위와 같다.
다음 글에서 이야기하겠지만 기존의 세션기반 인증은 서버에서 사용자 정보를 저장하고 있어 인증을 위해 이를 조회하는 작업이 필요했는데, 토큰 기반 인증은 사용자 정보가 서버가 아닌 클라이언트에 저장되기 때문에 서버의 부담을 줄일 수 있다.
JWT는 json web token의 약자이다. 즉 인증에 필요한 정보들을 암호화시킨 JSON 토큰이다.
JWT는 3가지(header, payload, signature)가 '.'로 구분되어 이루어져 있다.
토큰의 헤더는 typ(타입)과 alg(알고리즘) 두 가지로 구성된다.
{
"alg" : "HS256",
"typ" : JWT
}
페이로드에는 토큰에 담을 정보가 담겨있다. 이 정보의 한 조각을 클레임(claim)이라고 하고, name/value로 이루어져 있다.
이 클레임은 총 3가지로 나누어진다.
등록된 클레임은 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터들로, 모두 선택적으로 작성하지만 사용할 것을 권장한다.
또, jwt를 간결하게 하기 위해 key는 3글자로 통일한다.
공개 클레임은 사용자 정의 클레임으로, 공개용 정보를 위해 사용된다. 출돌 방지를 위해 uri 포맷을 이용한다.
비공개 클레임은 마찬가지로 사용자 정의 클레임이고, 서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다.
서명은 토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다. 서명은 위에서 만든 헤더와 페이로드의 값을 Base64Url로 인코딩하고, 인코딩한 값을 secret key를 이용해 헤더에서 정의한 알고리즘으로 해싱하고, 그 값을 다시 Base64Url로 인코딩하여 생성한다.
-> 이렇게 생성된 토큰은 http 통신을 할 때 Authorization key의 value로 사용된다. 일반적으로 value 앞에 "Bearer"이 앞에 붙는다.
{
"Authorizaion" : "Bearer {토큰}"
}
여러 정보가 담긴 access token이 제3자에게 탈취당할 경우 위험할 수 있다는 것이 위 토큰 방식의 문제였다.
토큰이 발급된 이후, 서버에 토큰을 저장하지 않고 누구든지 그 토큰을 가지고 있다면 인증되기 때문에 토큰이 만료되기 전까진 누구나 접근 권한이 생긴다.
서버에서 토큰을 발급한 후에 삭제가 불가능하기 때문에 토큰의 만료기한을 잘 설정하는 것 외에는 대응할 방법이 없었다.
그러나 기한을 짧게하면 사용자의 편의성이 떨어지고 길게하면 보안상 위험이 커지는 것이다.
-> 이때 기한을 짧게 하면서 편의성을 떨어뜨리지 않는 방법이 Refresh Token이다.
access token, refresh token 모두 똑같은 jwt 토큰이다. 단지 역할이 다른데, access token은 접근에 관여하고, refresh token은 재발급에 관여한다.
간단하게 보면
정도이다. 구체적인 로직은 상황에 따라 바뀔 수 있다.
참고
https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC
https://mangkyu.tistory.com/56