인증(Authentication) 그리고 인가(Authorization)
인증, 권한 체크 이해하기
쿠키? 세션? 인증? 권한? 무엇인지 이해하려면, MONEY MONEY해도 역사 배경을 알면 빠르게 이해할 수 있다. 이제부터 그 역사를 파해쳐보자
Web의 탄생, 그리고 HTTP
만약 당신이 도서관에서 책을 빌리려고 한다. 무엇이 필요한가?
- 당신은 도서관에 가입해야한다.
- 도서관은 여러분의 신분은 확인하고 확인증(회원증)을 발급해준다. (종이일 수도, 카드의 형태일 수도)
- 이제 여러분은 발급된 확인증으로 도서관을 출입하고, 대여 또는 대출을 받을 수 있다.
여기서 인증과 인가, 권한 확인과 같은 일련의 과정이 생깁니다.
자, 다시 돌아와서.
기술과 컴퓨터의 발명, 그리고 Web(www)의 개발로 이제는 네트워크만 연결되면 모든 것을 처리할 수 있는 시대에 살고 있습니다. HTTP통신으로 서버와 클라이언트가 생겨났고, 누구는 서비스를 제공하고 누구는 서비스를 이용합니다.
하지만 온라인 생태계에서 서비스 이용자(User)를 어떻게 확인할까요?
먼저, HTTP의 특징과 생태계를 이해해야 합니다. 여기 HTTP 통신 하는 방법이 그림으로 나타내져 있습니다.
HTTP의 특징
비연결성(connectionless)
한번의 request/response 의 결과로 클라이언트가 서버의 응답을 받은 후, 서로 접속을 끊게 된다.이러한 특징은 서버의 자원 낭비를 줄일 수 있다는 장점이 있다.
비상태성(stateless)
비연결성과 긴밀한 특징으로 비상태성이다. HTTP가 요청 처리 후 연결을 끊어버리기 때문에, 클라이언트의 상태 정보가 남아있지 않는다. 다음 요청에서 이전 요청에 대한 정보를 가지고 있지 않아 매번 갱신을 해야한다. 그 요청이 로그인이라면, 로그인 창이 유지되지 않고 브라우저를 새로 켤 때마다 매번 로그인을 해야하는 것이다.
이렇게 HTTP의 비연결성과 비상태성을 보완하여 서버가 클라이언트를 식별하게 하기 위해 아래와 같이 몇가지 방안을 사용한다.
쿠키(Cookie)
사용자 인증 여부를 매번 서버에 저장하는 것은 큰 부하가 발생합니다. 그렇기 때문에 인증이 이루어지면, 인증 정보를 사용자에 돌려주고, 사용자는 이미 인증 받은 내역을 가지고 다시 서버에 방문하는 거죠. 그러면 더이상 인증 절차는 이루어질 필요가 없는 것입니다.
하지만, 비상태성
을 가지는 HTTP 프로토콜에서 어떻게 사용자 인증 정보를 저장할 수 있을까요? 이때 등장한 기술이, 쿠키
입니다.
개념
쿠키란 인터넷 사용자가 웹 사이트를 방문할 때, 사용자의 컴퓨터에 설치되는 작은 기록 정보 파일을 말한다. 쿠키라는 네이밍은 웹 사이트를 방문할때마다 쿠키 부스러기처럼 사용자 컴퓨터에 임시파일들이 생기는 게 비슷하여 지어졌다고 한다.
브라우저마다 저장되는 쿠키는 다르다. 서버에서는 브라우저가 다르면 다른 사용자로 인식한다. 예를들어, 크롬으로 남긴 쿠키는 인터넷 익스플로어에서 사용할 수 없다.
쿠키는 세션 관리, 개인화, 트래킹 등의 목적으로 이용되어지고 있습니다. 초창기에는 쿠키에 사용자 인증 정보를 저장하고 이용했습니다. 사용자는 더이상 ID와 PASSWORD를 매번 입력할 필요가 없어졌습니다. PC를 재부팅해도 웹브라우저로 사이트를 이동하면 바로 로그인이 되었죠.
단점
- 임의로 고치거나 지울 수 있고, 가로채기 쉬워 보안에 취약하다.
- 용량 제한으로 인해 많은 정보를 담을 수 없다.
- 웹 브라우저마다 쿠키에 대한 지원 형태가 다르기 때문에 브라우저 간 공유가 불가능하다.
가장 문제가 불러졌던 부분은 보안에 취약
이였습니다. 초창기에는 ID, PASSWORD를 평문으로 쿠키에 저장하는 곳도 있었죠.
세션(Session)
이러한 환경 속에서 세션
이라는 녀석이 등장합니다. 클라이언트의 사용자 인증 정보를 사용자 컴퓨터가 아닌 서버에 저장하고 관리하죠. 일정 시간동안 같은 사용자(브라우저)로부터 들어오는 일련의 request 를 하나의 상태로 보고, 그 상태를 일정하게 유지시키는 기술입니다.
즉, 방문자가 웹 서버에 접속해있는 상태를 하나의 단위로 보고 이를 세션이라고 한다.
여러분의 인증 정보(ID, PASSWORD)를 시스템에 입력하면, 시스템(서버)은 여러분의 인증 정보를 확인 후, 입장권을 주겠죠?
세션에서는 이것이 SESSION ID
가 됩니다. SESSION ID를 공격자가 알아낸다고 하더라도, 그 안에는 사용자의 민감한 정보의 조합이 있지 않습니다. (보통의 구현에서는..) 또한 위의 이미지에서도 나오다시피, 매 요청(REQUEST)마다 서버는 쿠키에 저장된 세션을 검증하는 절차를 진행할 수 있습니다. 만약, 세션 정보(SESSION ID)가 유효하지 않다면, 응답하지 않거나 로그인 페이지로 강제로 이동시키거나 하겠죠.
즉, 여러분의 인증 정보(SESSION)는 서버가 담당한다는 소리입니다.
아래는 유튜브(코딩애플)에서 매우 간단히 잘 설명한 내용을 캡처했습니다. (이해가 매우 쉽다.)
요약
- 쿠키를 포함한 요청이 외부에 노출되어도 Session ID 자체는 유의미한 개인 정보를 담지 못한다.
- 각 사용자마다 고유한 Session ID가 발급되기 때문에, 요청이 들어올 때마다 로그인할 필요가 없다.
- 서버가 세션 정보를 관리하므로 서버가 노출되지 않는한 매우 안전하다
만약 SESSION ID를 쿠키에 저장하고, 공격자에 의해 SESSION ID가 탈취 당한다면?
보통 이럴 때는 다양한 보호 메커니즘을 도입할 수 있겠지만, 가장 쉬운 것은 SESSION에 유효 시간을 부여하는 방법이다. SESSION에 유효시간이 지나면 서버는 새로운 SESSION ID를 발급 하므로, 공격자는 기존 SESSION ID로는 더이상 서비스를 이용할 수 없다.
세션의 한계 (Limitation)
처음에는 세션이 매우 잘 동작했을 것이다. 물론 지금도 그렇다.
하지만, 전 세계가 글로벌화되고 네트워크로 서로 통신할 수 있게 되었으며, 사용자가 전 세계 인구를 대상으로 하는 엄청난 서비스들이 등장하였고, 이 서비스안에 또다른 서비스가 생겨나고…(뭐이리 복잡해짐?)
이러한 상황은 세션 기술력에 한계가 보이기 시작하는데.
세션의 인증 처리는
서버
가 담당한다???
처음에야 이게 잘 동작했겠지만, 만약 1억 명의 사용자가 DB에 있으며, 1억개의 세션 정보가 있다라고 하면 어떻게 될까?
1명을 위해 1억개의 데이터를 훑어봐야 한다는 소리다. 아무리 컴퓨터라지만 인증에만 리소스를 온전히 쏟게되고 자원 낭비, 시간 낭비, 응답 속도 느려짐 등등 엄청난 이슈가 발생하게 되겠지. 그렇다고 컴퓨터의 H/W 스펙(SCALE UP
)을 늘리는데는 비용과 H/W한계가 존재하며, 여러대를 늘리자니 (SCALE OUT
) 이또한 관리가 힘들어지고 비용이 늘어나는 문제가 발생하게 된다.
JWT(JSON Web Token)
JWT
는 세션과 틀린데, 자세한 정의는 위키피디아나 관련 사이트를 참고해라.
선택적 서명 및 선택적 암호화를 사용하여 데이터를 만들기 위한 인터넷 표준으로, 페이로드는 몇몇 클레임(claim) 표명(assert)을 처리하는 JSON을 보관하고 있다. 토큰은 비공개 시크릿 키 또는 공개/비공개 키를 사용하여 서명된다. 이를테면 서버는 “관리자로 로그인됨”이라는 클레임이 있는 토큰을 생성하여 이를 클라이언트에 제공할 수 있다. 그러면 클라이언트는 해당 토큰을 사용하여 관리자로 로그인됨을 증명한다. 이 토큰들은 한쪽 당사자의 비공개 키(일반적으로 서버의 비공개 키)에 의해 서명이 가능하며 이로써 해당 당사자는 최종적으로 토큰이 적법한지를 확인할 수 있다. 일부 적절하고 신뢰할만한 수단을 통해 다른 당사자가 상응하는 공개키를 소유하는 경우 이 경우 또한 토큰의 적법성 확인이 가능하다. 토큰은 크기가 작고 URL 안전으로 설계되어 있으며 특히 웹 브라우저 통합 인증(SSO) 컨텍스트에 유용하다. JWT 클레임은 아이덴티티 제공자와 서비스 제공자 간(또는 비즈니스 프로세스에 필요한 클레임)의 인가된 사용자의 아이덴티티를 전달하기 위해 보통 사용할 수 있다.
세션과의 차이점
유튜브 너무 잘 설명되어 있어서 계속 차용하려고 한다.
JWT와 세션의 가장 큰 차이점은
- 인증 정보(회원증 또는 티켓이라고 생각하면)를 누가 가지고 있으며 처리하나?
- 세션 : 서버가 가지고 있어서 매번 SESSION STORE에서 SESSION ID의 유효성을 찾아 검사한다.
- JWT : 사용자가 전달한 인증 정보(JSON WEB TOKEN)룰 서버는 가지고 있지 않는다. 즉, 사용자가 전달한 내용만 확인하고 유효하면 서비스를 제공하면 된다.
JWT에서 인증 서버는 전달받은 토큰의 내용만 훑어볼 뿐이다.
그렇기 때문에 세션보다 JWT가 훨씬 빠르고 가벼운 것이다.
JWT 구조 (Header, Payload, Signature)
JSON은 점(.)으로 구분된 세 부분으로 구성되며 다음과 같다.
Header
Header는 JWT인 토큰 유형과 HMAC SHA256 또는 RSA와 같이 사용중인 서명 알고리즘 두 부분으로 구성된다. Alg는 서명 시 사용하는 알고리즘이고, type 토큰 유형이다.
그 후 이 JSON을 Base64Url로 인코딩하면 JWT의 헤더부분인 첫 부분을 형성한다.
Payload
JWT의 두번째 부분은 Payload이다. 페이로드의 속을 클래임 셋(Claim Set)이라고 부른다. 클레임은 사용자 추가 데이터에 대한 설명이다.
페이로드는 Base64Url로 인코딩되어 JSON의 두 번째 부분을 형성한다.
Signature
서명 부분을 생성하려명 인코딩된 Header, Payload, secret, Header에 저장된 알고리즘을 가져와 서명해야 한다. 서명은 메시지가 도중에 변경되지 않았는지 확인하는 데 사용되며 개인로 서명된 토큰의 경우 JWT를 보낸 사람이 누구인지 확인할 수 있다.
예를 들어 HMAC SHA256 알고리즘을 사용하는 경우 서명은 다음과 같은 방식으로 생성된다.
다음은 Header와 Payload로 인코딩되어 있고, secret으로 서명된 JWT이다. 이러한 개념을 JWT 디버거를 사용하여 디코딩, 확인 및 생성할 수 있다.
[출처] : https://blog.bespinglobal.com/post/server-서버-인증-이해하기-4부-oauth-확장편/
이와 같은 특징 때문에 JWT는 엄청나게 많이 쓰이고 있다.
취약점
항상 그렇듯이, 그 어떠한 것도 완벽하지 않다. JWT도 만능이 아니다. JWT도 취약점이 있으며, 때로는 개발자가 자기도 모른사이에 취약점을 수정하지 않고 서비스를 제공할 수도 있다.
다음 포스팅에서는 JWT의 취약점과 이를 해결할 수 있는 방법들은 소개하려 한다.
Leave a comment