클라이언트 인증의 역사
이전 HTTPS는 어찌보면,클라이언트에게 신뢰된 웹 서비스를 제공하기위해, 검증과정을 거친
웹애플리케이션 측에 대한 인증이라고 볼수 있다.
하지만, 반대로 웹 애플리케이션도 신뢰할만한 클라이언트를 확인할 필요가 있다.
이번에는 클라이언트를 인증하는 방식에 대해 순차적으로 알아보자
인증의 역사
HTTP의 특징
- stateless
- HTTP 통신에서 서버는 클라이언트의 상태를 저장하지 않는다.
- 서버와 클라이언트 정보 공유에 대한 비용을 최소화하기 위함이다.
- 이로써 (정보가 많으면 서버가 힘들기에)서버의 역할을 확장 시키기 유용하기때문이다.
- connectionless
- 연결을 유지하지 않는 것을 기본 동작으로 가진다.
- 이것 또한, (연결을 유지하는 동안 서버에 대한 비용이 들기때문에) 다수의 클라이언트를 상대해야하는 서버는 비연결성을 가진다.
Cookie
서버가 클라이언트 유저에 대해 아는 정보가 없기 때문에, 이 역할을 클라이언트에게 넘겨
매 요청시 마다 누군지 확인하겠끔 만들었는데,
이 특성을 보완하기 위해 나온게 Cookie이다.
cookie
는 클라이언트 로컬에 저장되어 있으며 key와 value로 구성된 작은 데이터 파일
cookie
는 저장 가능 용량이 적으며 보안에 있어 매우 취약하다(결제 정보 등).
- 특히 공용 컴퓨터를 이용하여 로그인할 경우, 여러 개인정보가 공용 컴퓨터에 남게 됩니다.

장점
- 이 덕분에, 사용자(클라이언트는) 웹서비스에서 한번 입력하여 로그인을 해놓으면, 또다시 로그인을 입력해야할일은 사라진다.
- 게다가, 서버는 아무런 정보를 저장하지 않아도 되, 서버에게도 부담이 없다.
단점
- 하지만, 쿠키는 사용자에게 저장되어 있기 때문에, 임의로 고치거나 지울수 있고, 가로채기도 쉽다.
- 만약, 아주 중요한 정보인 개인정보가 쿠키방식으로 주고받게되면, 보안에 매우 취약하다.
사용예시
- 그래서 중요한 정보가 아니며, 사용자마다 다른 서비스를 제공해줘야하는 경우에 많이 사용합니다.
- 또한, 사용자의 패턴과 행동을 분석하고 수집용으로도 많이 사용합니다.
- 팝업창 일주일간 다시 보기 않기
- 쇼핑몰 장바구니 기능
- 최근 검색한 상품들을 광고에서 추천
- 로그인상태유지(이경우는 아래 다시 언급)
Session
cookie의 단점인 개인정보 보안에 취약한 점을 해결하기위해 나온 기술이 session이다.
- 웹으로 들어오는 HTTP Request만 가지고 서버는 누가 누군인지 파악해야한다. 그래서 크게 사용자를 3가지로 분류하는데,
- 1번. 처음 방문한 사용자
- 2번. 방문한적은 있지만, 로그인하지 않은 사용자
- 3번. 로그인을 이미 한 사용자(더 자세히 들어가면 로그인 한지 얼마안된 사용자와, 오래된 사용자로 나눌 수 있긴하다.)
처음 방문한 사용자
- 웹 서버는 위 3가지 경우 다 Session ID를 발급해 준다.
- 웹 브라우저 당 1개씩 생성되어 웹 컨테이너(서버측 어딘가)에 저장시켜놓고, 브라우저 종료시 소멸된다.
- 즉, 웹 서비스에 처음 방문 했다면, 서버는 Session ID를 발급해 준다는 것이다.
- 물론 Session ID는 클라이언트 쿠키에 저장된다.

방문한적 있지만, 로그인하지 않은 사용자
- 서버가 Session ID생성하고, 소멸되기 전까지는 메모리에 보관해두기 때문에, 이전 기록이 저장되어 있다.
- 만약 쇼핑몰이라면, 방문자가 검색한 이력, 찜목록, 장바구니등을 로그인없이도 확인 가능하다.
- Session ID가 살아있다면, 방문자가 다른 곳을 방문하였다 재방문하더라도 기록이 남아있는 것이다.
- 세션ID 확인하는 로직은 여러방법이 있지만, 복잡하고 딥해지니 생략하였다.

로그인을 이미 한 사용자
- 위 방문자의 경우와 매우 유사하다.
- 이번엔, 로그인후, 로그인이 유지되는 흐름까지 구현해 봤다.
- 그리고, 서버에서 굳이 새로운 sessionID를 만들지 않고, 서버에 sessionID를 관리하는 DB가 있어, 회원인지 아닌지를 저장해놓을 수 도 있다.

장점
- 사용자의 중요정보가 노출되지않아, 쿠키보다 보안성이 좋다.
- 서버에 저장됨으로 클라이언트의 웹 브라우저에 의존하지 않아도 됨.
- 데이터를 Hash Table에 저장(한번에 많은 정보를 하나의 세션 객체에 저장가능)
- 응답으로 보낼땐, SessionID만 보내므로, 매우 작은 용량으로 전송된다.
단점
- 서버가 모든 것을 다하려고 하다보니, 서버의 부하가 크다.
- 만약, 서버가 처리할 수 있는게 200인데, 동시에 500명~1,000명등의 요청이 들어오게되면 서버가 터진다.
- 위 문제를 해결하기위해 서버를 늘리는 경우에는, session ID 가 공유되지 않는 문제가 발생한다.
- SessionID를 공유하기위해서, 서버들이 공통으로 접속하는 DB에 sessionID를 저장하게되면, 로그인 확인시마다, DB를 접근하게된다.
- 또한, 트래픽이 DB로 몰리게되어, DB가 매우 느려진다.
결국 보안적으로는 해결되었으나, 동시접속자가 많아진다면 서버가 감당 못하게되는 문제점이 나온다.
그래서 이러한 방식을 해결하기위해, 토큰방식과 서버분산방식이 나온다.
토큰과 서버분산
서버 분산
-
요즘은 많은 서비스들이 서버 과부하 부담을 줄이기 위해 여러서버(scale-out)를 두고 운영한다.
-
하지만, 서버가 많으면 아래처럼, session ID는 공유하지 않아 또다시 Session ID를 만들게 된다.

-
이러한 문제를 해결하는 여러 방법들이 있지만, 가장 대표적인게 토큰 방식이다.
- sticky session : 처음 지정받은 서버만 사용할 수 있다.
- session clustering : 모든 서버마다 세션을 복사
- 이러한 방식들은 상당한 메모리를 요구할 뿐 아니라 매 로그인마다 오버헤드가 크게 발생합니다.
- 물론 세션용 서버를 따로 두는 방법도 있다.
토큰
어찌보면, 토큰 인증방식은 sessionID 값이 여러개 생성되는 문제를 해결해주는 방법이라기 보다는,
애초에 로그인 정보를 굳이 서버나 DB에 저장해야할까? 에 대한 해결 방법이다.
- 토큰 방식은 로그인했다는 정보를 비교하는 과정을 서버나 DB에 저장하지 않고도 처리할 수 있다.
토큰 동작 방식
- 클라이언트가 서버에 ID/PW를 담아 로그인 요청을 보낸다.
- 서버는 DB에 사용자 정보가 일치하는 지 확인하고, 일치한다면 토큰을 암호화하여 생성한다.
- access토큰, Refresh 토큰 모두 생성한다.
- 토큰에 담길 정보는 유저를 식별할 정보, 권한이 부여된 카테고리 등이 될 수 있다.
- 토큰을 쿠키에 저장하라고, 클라이언트에게 응답해준다.
Local Storage
나 Session Storage
등, 클라이언트의 다른 저장소에 저장할 수도 있다.
- 다시 클라이언트가 웹서비스에 접근할 때에는, HTTP 헤더 또는 쿠키에 토큰을 담아 보낸다.
- 서버는 토큰을 복호화해보니까, 서비스만의 회원을 인증할 데이터가 있음을 확인하고, 응답을 해준다.

가장 많이 쓰이는 JWT
JSON Web Token으로 Json으로 통신을 많이하는 웹에서 쓰이는 토큰을 말한다.
데이터를 안전하고 간결하게 전송하기 위해 고안된 인터넷 표준 인증 방식이다.
JWT 종류
- JWT도 다른 토큰과 마찬가지로 두 가지 종류의 토큰을 이용해 인증을 구현한다.
- 액세스 토큰(Access Token)
- 리프레시 토큰(Refresh Token)
액세스 토큰
- 보호된 정보들(유저의 이메일, 연락처, 사진 등)에 접근할 수 있는 권한부여에 사용한다.
- 실제로 클라이언트에게 전달하는 권한을 얻는 데 사용하는 토큰이다.
- 비교적 짧은 유효 기간 을 주어 탈취되더라도 오랫동안 사용할 수 없도록한다.
- 만료되었다면, 리프레시 토큰을 사용하여 다시 엑세스 토큰을 발급받는다.
리프레시 토큰
JWT 구조
- WT는 아래 그림과 같이
.
으로 나누어진 3부분이 존재합니다.
- Header
- Header는 이것이 어떤 종류의 토큰인지(지금의 경우엔 JWT), 어떤 알고리즘으로 sign할지가 적혀있습니다.
- JSON Web Token이라는 이름에 걸맞게 JSON 형태로 보실 수 있습니다.
- Payload
- Payload에는 서버에서 활용할 수 있는 유저의 정보가 담겨 있습니다.
- 어떤 정보에 접근 가능한지에 대한 권한을 담을 수도 있고, 사용자의 유저 이름 등 필요한 데이터를 담을 수 있습니다. Payload는 다음으로 설명할 Signature를 통해 유효성이 검증될 정보이긴 하지만, 너무 민감한 정보는 되도록 담지 않는 것이 좋습니다.
- 첫 번째 부분과 마찬가지로, 위 JSON 객체를 base64로 인코딩하면 JWT의 두 번째 블록이 완성됩니다.
- Signature
- base64로 인코딩된 첫 번째, 그리고 두 번째 부분이 완성되었다면, Signature에서는 원하는 비밀 키(암호화에 추가할 salt)와 Header에서 지정한 알고리즘을 사용하여 암호화합니다.
- 즉, base64 인코딩 자체는 누구나 쉽게 디코딩할 수 있어 Header와 Payload 모두 쉽게 확인할 수 있지만 비밀키를 사용해 이를 암호화한 값(시그니처)은 비밀키를 보유한게 아니라면 해독해내는데 엄청난 시간과 노력이 들어갈 겁니다!
- 예를 들어, 만약 HMAC SHA256 알고리즘(암호화 방법 중 하나)을 사용한다면 Signature는 아래와 같은 방식으로 생성됩니다.
- HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);
장점
- 무상태성과 확장성(Statelessness & Scalability)의 특징을 가지고 있다
- 서버는 클라이언트에 대한 정보를 저장할 필요 없습니다. (토큰 해독이 되는지만 판단)
- 클라이언트는 새로운 요청을 보낼 때마다 토큰을 헤더에 포함시키면 된다.
- 서버를 여러 개 가지고 있는 분산 서버의 경우, 여러서버에서 Session 생성없이 인증이 가능하다.
- 안전하다
- 암호화한 받은 토큰을 사용하고, 암호화 키를 노출할 필요가 없기 때문에 안전하다.
- 어디서나 생성 가능하다
- 토큰을 확인하는 서버가 토큰을 만들어야 하는 법이 없기 때문에, 토큰 생성용 서버를 만들거나, 다른 회사에서 토큰관련 작업을 맡길 수 있다.
- 권한 부여에 용이하다
- 토큰의 Payload(내용물) 안에 해당 유저가 어떤 정보에 접근 가능한지 정할 수 있다
단점
추후 내가 더 알아보고 싶은 것
- 리프레시 토큰과 엑세스 토큰의 관계 및 생성과정
- 서브파티관련한 동작 방식
- 다른 회사에서 토큰관련 작업을 맡기는 Oauth2.0
- JWT와 Oauth2.0의 관계
참고링크