사용자 로그인 후 로그인 상태를 유지하지 않는다면 어떤 일이 발생할까?
만약 네이버에서 블로그 글을 작성하는 상황이라면, 로그인을 했음에도 블로그글을 작성할 때에도 사용자 아이디와 비밀번호를 함께 작성한 블로그글과 함께 서버에 전달해야하고 서버는 또 다시 그 아이디와 비밀번호를 유저테이블에서 비교후 사용자 인증을 거치고 블로그 글을 저장해야하는 번거롭고 소모적인 작업을 매번 반복해야할 것이다.
위와 같은 불편한 작업을 줄이고자 '로그인 상태를 유지' 하는 것이 필요한 것이다.
쉽게 말해 로그인을 'Authentication(인증)' 이라한다면, 로그인상태를 유지하는 것 'Authorization(인가)'라고 한다.
'Authorization'을 위한 방법엔 크게 2가지가 있는데, 1) Session 방식 2) Token방식이 있다.
전통적으로 많이 사용되어온 '세션'방식은 어떤 식으로 사용자 인가를 하는지 알아보자.
session방식으로 사용자 인가를 구현했을 때 여러 서버를 운용하는 서비스의 경우 세션정보를 어디에 어떻게 보관할 것인지 구상하고 관리하는 등 설계가 꽤 복잡하다는 단점이 존재했다.
그래서 그런 부담없이 인가를 구현하기 위해 고안된 것이 "Token 방식인 JWT(Json Web Token)"이다.
token방식으로는 어떻게 사용자 인가를 하는지 알아보자.
위의 과정 2번에서 보듯 서버는 token을 발급하여 클라이언트에게 전달하기만하고 서버측에 따로 해당 token을 저장해두진 않는다.
( 이점이 session방식에선 세션저장소를 필요로하는 것과는 대조적이다. )
사용자에게 발급되는 token은 위사진의 왼쪽과 같은 형태를 갖게된다.
마침표(.)로 끊어져서 세 부분으로 나뉘는데
각각 header, payload, verify signature로 구분된다.
payload
header
verify signature
=> 그러므로 이제는 서버는 사용자들의 상태를 어딘가에 따로 기억해 둘 필요 없이 secret key만 갖고 있으면 요청이 들어올 때마다 token을 비교해 사용자를 걸러낼 수 있게된다.
이러한 것을 stateless하다고 말한다. (반면, 일일히 사용자 저마다의 세션정보를 서버가 알고 있어야하므로 session 방식은 stateful하다.)
위에서 말했듯 session은 stateful해서 사용자의 상태를 기억하고 있기때문에 언제든 제어할 수 있다는 장점이 있다. 반면 JWT는 그렇지 않아서 언제든 사용자를 제어하긴 힘들다는 단점이 있다.
그렇다고 session방식처럼 발급한 token을 서버측 어딘가에 저장해두는 건 session방식과 다를 바 없기 때문에 token방식으로써의 의미가 없어진다.
더 심각한 경우는 token이 탈취된 경우 해당 token을 무효화할 방법이 없다는 점이다.
(이 때문에 JWT만으로 인가를 구현한 곳은 생각보다 많지 않다고 한다. )
위의 치명적인 단점을 보완하기 위해 쓴 방법들이 있는데
token만료시간을 매우 짧게 주는 것이다. 수명이 짧으므로 서비스를 이용하는 동안 지정된 시간이 지났을 때마다 다시 로그인을 시키는건 사용자 입장에서 불편하므로
로그인을 하고나면 2개의 토큰을 준다.
"access token"과 "refresh token"이다.
(앞으로 말하게 될 인가 방식은 여러 방법 둘 중에 하나일 뿐이라는 걸 염두하고 보자)
서버는 access token과 refresh token을 발급하여 클라이언트에게 보내고 나서 refresh token의 상응값을 데이터베이스에도 저장한다.
클라이언트는 데이터 요청을 할때 access token을 보내는데 수명이 다했다면 refresh token을 보낸다.
서버는 그걸 데이터베이스에 저장된 값과 대조해본 뒤 맞다면 새로운 access token을 발급해준다.
이제 이 refresh token만 안전하게 관리된다면 access token이 만료될때마다 다시 로그인할 필요 없이 새로 발급할 수 있는 것이다.
=> 이렇게 하면 중간에 access token이 탈취당해도 새로 access token을 발급받진 못하니까 오래 쓸 수는 없고 누군가 강제 로그아웃을 시키고 싶다면 그 사용자의 refresh token을 데이터베이스에서 지워서 토큰 갱신을 막으면 된다.
( 물론 유효기간이 아직 남은 access token이라면 그 잠시 동안은 제어할 수 없다..)
JWT의 장단점, Session의 장단점을 고려해 서비스에 적합한 인가방식을 선택하자!
참고
https://www.yalco.kr/48_jwt/
https://tansfil.tistory.com/58?category=475681
https://jwt.io/