인증(Authentication) : 사용자의 신원을 확인하는 행위
인증 은 특정 리소스에 접근하려는 사용자가 누구인지 확인할 때 사용합니다.
일상 생활에 비유해보면 회사에서는 출입증 또는 생체정보를 통해 출입하려는 사람의 신원을 확인합니다.
웹에서는 보통 아이디와 패스워드를 이용하여 로그인을 통해 본인임을 증명합니다.
인가(Authorization) : 사용자의 권한을 확인하는 행위
일반적으로 사원의 권한에 따라 건물 내 접근할 수 있는 회의실, 사무실이 제한됩니다.
웹에서도 사용자에 관리자/사업자/랭킹 등 권한을 부여할 수 있습니다.
웹에서 사용하는 HTTP는 TCP/IP
위에서 작동하는 비연결, 무상태 프로토콜입니다.
1) 비연결지향
HTTP는 먼저 클라이언트가 request를 서버에 보내면, 서버는 클라이언트에게 요청에 맞는 response를 보내고 접속을 끊어버립니다.
2) 상태정보 유지안함
연결을 끊는 순간 클라이언트와 서버의 통신이 끝나며 상태 정보는 유지하지 않는 특성이 있습니다.
따라서 클라이언트는 페이지를 옮겨다닐 때마다 로그인을 다시해서 내가 누구인지 계속 인증해야하는 단점이 있습니다.
이 단점을 극복할 수 있는 방법에 대해 하나씩 살펴보도록 하겠습니다.
세션은 일정 시간동안 같은 브라우저로부터 들어오는 상태정보를 서버 메모리 공간에 저장함으로써 상태를 유지하는 기술입니다.
웹 브라우저마다 별도의 세션을 갖게되는데 서버(WAS)는 각 세션을 구분하기 위해 세션마다 고유한 세션 ID를 부여합니다.
(조금 더 구체적으로 말하자면 서버에서 생성한 JSESSION ID를 HTTP Set-Cookie 헤더 에 실어 클라이언트에 보내게 됩니다)
클라이언트는 전달받은 세션 ID를 쿠키에 저장합니다.
쿠키는 브라우저 쿠키 저장소에 저장되는 데이터로, 서버에 연결할 때마다 매번 세션 ID를 보내서 웹 서버가 어떤 세션을 사용할지 판단할 수 있도록 합니다.
그러나 세션 방식은 서버의 메모리 자원을 사용하기때문에 무분별하게 만들다보면 서버의 메모리가 감당할 수 없어질 수가 있고 속도가 느려질 수 있습니다.
마찬가지로 서버의 메모리 공간에 세션 데이터가 저장되기 때문에 서버가 여러대로 늘어나는 경우 세션 데이터 공유가 까다로워집니다.
JWT(JSON Web Token)는 인증에 필요한 정보들을 암호화시킨 토큰을 의미합니다.
로그인 성공시 서버는 유저 정보를 담은 토큰을 생성해 클라이언트에게 전달합니다.
클라이언트는 토큰을 HTTP 헤더에 실어 서버에 전송합니다.
토큰 자체 내부에 유저의 정보가 들어가있기 때문에, 세션과 달리 서버는 클라이언트와 관련한 어떤 데이터도 관리하지 않습니다.
JWT 토큰은 위와 같이 헤더, 페이로드, 서명 3가지 데이터가 암호화된 문자열입니다.
페이로드는 토큰의 유효 기간, 서비스가 사용자에게 이 토큰을 통해 공개하길 원하는 내용(Claim) 등에 대한 정보를 담고있습니다.
헤더는 토큰의 타입(JWT 고정값), 서명값을 만드는데 사용할 알고리즘(위 예시에서는 HS256)에 대한 정보를 담고 있습니다.
헤더와 페이로드, 그리고 '서버에 감춰놓은 비밀값'을
이 암호화 알고리즘에 넣고 돌리면 서명값이 나오게됩니다.
따라서 토큰을 탈취한다고 해도 서버에 감춰놓은 비밀값을 모르기 때문에 조작을 하더라도 서명값도 달라지기 때문에 조작이 불가능하게 됩니다.
그러나 토큰은 한번 발급하게되면 서버에 제어권이 없습니다.어떤 토큰이 탈취되었다고 하더라도 그 토큰을 무효화할 방법도 없습니다.
이 때, 2가지 토큰(access 토큰, refresh 토큰)을 발급하여 이 문제를 개선할 수 있는데 수명이 짧은 access 토큰과 수명이 긴 refresh 토큰을 발급해주고 refresh 토큰은 DB에 저장하여 관리합니다.
클라이언트는 매 요청시 access 토큰을, 유효기간이 끝났을때만 refresh 토큰을 서버에 전달하게 되는데 서버는 refresh 토큰을 전달받으면 DB값과 대조후 일치 시 다시 access 토큰을 부여하게 됩니다.
따라서 중간에 access 토큰을 탈취당하더라도 수명이 짧아 오래 쓰지는 못하기 때문에 완벽한 해결책은 아니더라도 어느정도의 위험성을 낮을 수 있습니다.(짧게나마 엑세스 토큰이 살아있는 동안에는 어쩔 수 없습니다)
이와 같이 서버에서 토큰에 대한 제어권이 없기때문에 토큰을 발급한 이후 시스템내 변경사항이 생기는 경우를 고려해야합니다.
예를 들어 토큰을 이미 발급한 이후 권한 체계가 바뀌는 경우 아래처럼 대처할 수 있습니다.
(1) 권한 DB에 Version 필드를 추가하고 권한이 수정될 때 Version을 올린다. JWT 내의 권한 Version 정보와 비교해서 다르면 Update 한다.
(2) JWT 페이로드에 발급 시간을 저장해 놓고 권한이 변경된 시간과 비교 업데이트한다.
https://tofusand-dev.tistory.com/89#token-%EA%B8%B0%EB%B0%98-%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D