1. 인증 Autehntication
- 로그인
- 특정 사이트에 가입된 회원임을, 일정 권한이 주어진 사용자임을 인증
2. 인가 Authorization
- 로그인이 유지된 상태에서 일어나는 일
- 인증 받은 사용자가 이후 서비스의 여러 기능을 사용할 때
- 자기 계정으로만 할 수 있는 활동을 시도할 때 로그인 되어있음을 알아보고 허가
사용자가 로그인한 사실을 서버가 인지할 수 있도록 하는 방법은?
- 서버는 각 요청이 들어올 때마다, 요청을 보낸 사용자가 인증 과정을 거친 상태인지 확인해서 서비스 기능을 허용 해줄지 말지 결정해서 응답
- DB에 저장된 사용자 계정의 Hash 값을 꺼내온 다음에 사용자 암호를 복잡한 알고리즘으로 계산한 값과 일치하는지 확인하는 과정을 거쳐야 해서 무거움
세션
- 전통적으로 많이 사용됨
- 로그인 성공 시 서버는 세션(영화관 티켓)을 출력하고, 이를 찢어서 반은 사용자의 브라우저로 보내고, 다른 반은 메모리에 올려 놓는다.
- 경우에 따라 하드디스크나 DB에 넣기도 한다.
- 브라우저는 티켓을
Session ID
라는 이름의 쿠키로 저장하여 사이트에 요청을 보낼 때마다 실어 보낸다.
- 서버에 로그인 되어있는 상태를 세션이라고 한다.
- 서버가 재부팅되어야 하는 상황이 오면 메모리에 있는 것들이 다 날아가게 되는 문제점이 있다.
Redis
나 MemCached
같은 메모리형 DB 서버에 올려두기도 한다.
- 서버가 복잡한 구성과 환경에서 어떤 상태를 기억해야 하므로 설계하기 어렵다.
JWT
- 세션의 문제점을 보완하고자 토큰 방식인 JWT 고안
- XML처럼 데이터 담을 때 쓰는 JSON의 Web Token
- 로그인 하면 서버는 토큰이라는 표를 출력해서 건제주는데 이번엔 찢어서 주지 않고 그대로 준다. (서버가 무언가를 기억할 필요 없다.)
- 인코딩 또는 암호화된 3가지 데이터를 이어 붙인다.
- 잘 보면 중간에 점, 마침표가 두 군데 들어가 3개의 구간으로 나뉜다.
- https://jwt.io/
- 각각 header, payload, verify signature로 구분된다.
Payload
- Claim : 토근에 담긴 사용자 정보 등의 데이터
- payload에서 Base64로 디코딩해보면 JSON 형식으로 여러 정보들이 들어가 있다. 누가 누구에게 발급했는지, 언제까지 유효한지, 서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용(사용자 닉네임, 관리자 여부 등)
- 토큰에 이런 정보들이 들어가 있어서 서버가 요청마다 일일이 DB를 뒤져봐야할 것들이 줄어든다.
- 토큰을 디코딩해서 임의로 조작할 수 있는 문제점이 존재한다.
- 디코딩하면 type은 항상 고정값 JWT이 들어간다. 다른 하나인 alg(알고리즘 약자)은 Verify signature 값을 만드는데 사용될 알고리즘이 지정된다. H256 등 여러 암호화 방식 중 하나를 지정할 수 있다.
- 헤더와 페이로드, 그리고 서버에 감춰놓은 비밀 값 이 3가지를 이 암호화 알고리즘에 넣고 돌리면 서명값이 나오는 것이다.
- 서버는 요청에 토큰값이 실려오면 헤더와 페이로드의 값을 서버의 비밀 키와 함께 돌려봐서 계산된 값이 서명값과 일치하는지 확인한다.
- 이처럼 시간에 따라 바뀌는 어떤 상태값을 갖지 않는 것을
stateless
라고 하는데, session은 반대로 stateful
하다.
결론
- JWT가 세션을 대체하기에는 큰 결점이 있다.
- 세션처럼
stateful
해서 모든 사용자들의 상태를 기억하고 있다는 건 구현하기 부담되고 고려사항이 많지만, 되기만 하면 기억하는 대상의 상태들을 언제든 제어할 수 있다는 것을 의미한다.
- 한 기기에서만 로그인 가능한 서비스를 만드려는 경우, PC에서 로그인항 상태의 사용자가 스마트폰에서 또 로그인하면 PC에서는 로그아웃되도록 기존 세션을 종료할 수 있다.
- JWT는 편하긴 한데 통제는 못하기 때문에 토큰을 무효화할 방법이 없다. 이를 보완하고자 만료시간을 가깝게 잡아서 토큰의 수명을 아주 짧게 해준다.
- 로그인 하면 토큰을 2개 주는데 수명이 짧은 access 토큰과 보통 2주 정도로 잡혀 있는 refresh 토큰이 있다.
- 위 둘을 발급하고 클라이언트에게 보내고 나서 refresh 토큰은 사응값을 DB에 저장한다. 따라서 사용자는 access 토큰의 수명이 다하면 refresh 토큰을 보내는데 서버는 이를 DB에 저장된 값과 대조해보고 맞다면 새로운 access 토큰을 발급해주는 형식이다.
- refresh 토큰만 안전하게 관리된다면 access 토큰이 만료될 때마다 다시 로그인할 필요 없이 새로 발급 받을 수 있게 된다.