봉봉의 개인 블로그
2019-07-18[카테고리 미분류](토큰(Token) 기반 인증에 대한 소개) 본문
토큰(Token)
토큰 기반 인증은 모던 웹서비스에서 정말 많이 사용되고 있다. API를 사용하는 웹서비스를 개발한다면, 토큰을 사용해 유저들의 인증 작업을 처리하는 것이 가장 좋은 방법이다.
토큰 기반 인증 시스템을 선택하는데에는 여러가지 이유가 있지만, 그중 주요한 이유들은 아래와 같다.
Stateless 서버
Stateless 서버를 이해하려면 먼저 stateful 서버가 무엇인지 알아야한다. stateful 서버는 클라이언트에게서 요청을 받을 때마다, 클라이언트의 상태를 계속해서 유지하고, 이 정보를 서비스 제공에 이용한다. stateful 서버의 예제로는 세션을 유지하는 웹서버가 있다. 예로 유저가 로그인하면, 세션에 로그인되었다고 저장을 해주고, 서비스를 제공할 때 그 데이터를 사용한다. 여기서 이 세션은, 서버컴퓨터의 메모리에 담을 때도 있고, 데이터베이스 시스템에 담을 때도 있다. Stateless 서버는 반대로, 상태를 유지하지 않는다. 상태 정보를 저장하지 않으면, 서버는 클라이언트측에서 들어오는 요청만으로만 작업을 처리한다. 이렇게 상태가 없는 경우 클라이언트와 서버의 연결고리가 없기 때문에 서버의 확장성이 높아진다.
모바일 어플리케이션에 적합
만약에 Android / iOS 모바일 어플리케이션을 개발 한다면, 안전한 API를 만들기 위해선 쿠키같은 인증시스템은 이상적이지 않는다. 토큰 기반 인증을 도입한다면, 더욱 간단하게 이 번거로움을 해결할 수 있다.
인증정보를 다른 어플리케이션으로 전달
대표적인 예로는, OAuth 가 있다. 페이스북/구글 같은 소셜 계정들을 이용하여 다른 웹서비스에서도 로그인 할 수 있다.
보안
토큰 기반 인증 시스템을 사용하여 어플리케이션의 보안을 높일 수 있습니다. 단, 이 토큰 기반 인증을 사용한다고 해서 무조건 해킹의 위험에서 벗어나는건 아니다.
왜 토큰을 사용하는가?
토큰 기반 인증 시스템이 어떻게 작동하고, 또 이로 인하여 얻을 수 있는 이득에 대하여 알아보기전에, 이 토큰 기반 인증 시스템이 어쩌다가 나타났는지 알아봅시다. 이를 위해선, 과거의 인증시스템이 어떤 방식으로 작동했는지 살펴볼 필요가 있습니다.
서버 기반 인증
기존의 인증 시스템에서는 서버측에서 유저들의 정보를 기억하고 있어야합니다. 이 세션을 유지하기 위해서는 여러가지 방법이 사용됩니다. 메모리 / 디스크 / 데이터베이스 시스템에 이를 담곤 하죠.
서버 기반 인증 시스템의 흐름을 보자면 다음과 같습니다.
이런 방식의 인증 시스템은 아직도 많이 사용 되고 있습니다. 하지만, 요즘 웹 / 모바일 웹 어플리케이션들이 부흥하게 되면서, 이런 방식의 인증 시스템은 문제를 보이기 시작했습니다. 예를 들자면, 서버를 확장하기가 어려웠죠.
서버 기반 인증의 문제점
세션
유저가 인증을 할 때, 서버는 이 기록을 서버에 저장을 해야합니다. 이를 세션 이라고 부릅니다. 대부분의 경우엔 메모리에 이를 저장하는데, 로그인 중인 유저의 수가 늘어난다면 어떻게될까요? 서버의 램이 과부화가 되겠지요? 이를 피하기 위해서, 세션을 데이터베이스에 시스템에 저장하는 방식도 있지만, 이 또한 유저의 수가 많으면 데이터베이스의 성능에 무리를 줄 수 있습니다.
확장성
세션을 사용하면 서버를 확장하는것이 어려워집니다. 여기서 서버의 확장이란, 단순히 서버의 사양을 업그레이드 하는것이 아니라, 더 많은 트래픽을 감당하기 위하여 여러개의 프로세스를 돌리거나, 여러대의 서버 컴퓨터를 추가 하는것을 의미합니다. 세션을 사용하면서 분산된 시스템을 설계하는건 불가능한것은 아니지만 과정이 매우 복잡해집니다.
CORS (Cross-Origin Resource Sharing)
웹 어플리케이션에서 세션을 관리 할 때 자주 사용되는 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어있습니다. 따라서 쿠키를 여러 도메인에서 관리하는것은 좀 번거롭습니다.
토큰 기반 시스템의 작동 원리
토큰 기반 시스템은 stateless 합니다. 무상태. 즉 상태유지를 하지 않는다는 것이죠. 이 시스템에서는 더 이상 유저의 인증 정보를 서버나 세션에 담아두지 않습니다. 이 개념 하나만으로도 위에서 서술한 서버에서 유저의 인증 정보를 서버측에 담아둠으로서 발생하는 많은 문제점들이 해소됩니다.
세션이 존재하지 않으니, 유저들이 로그인 되어있는지 안되어있는지 신경도 쓰지 않으면서 서버를 손쉽게 확장 할 수 있겠죠?
토큰 기반 시스템의 구현 방식은 시스템마다 크고작은 차이가 있겠지만, 대략적으로 보면 다음과 같습니다:
- 유저가 아이디와 비밀번호로 로그인을 합니다
- 서버측에서 해당 계정정보를 검증합니다.
- 계정정보가 정확하다면, 서버측에서 유저에게 signed 토큰을 발급해줍니다.
여기서 signed 의 의미는 해당 토큰이 서버에서 정상적으로 발급된 토큰임을 증명하는 signature 를 지니고 있다는 것입니다 - 클라이언트 측에서 전달받은 토큰을 저장해두고, 서버에 요청을 할 때 마다, 해당 토큰을 함께 서버에 전달합니다.
- 서버는 토큰을 검증하고, 요청에 응답합니다.
웹서버에서 토큰을 서버에 전달 할 때에는, HTTP 요청의 헤더에 토큰값을 포함시켜서 전달합니다.
토큰의 장점
무상태(stateless) 이며 확장성(scalability)이 있다.
이 개념에 대해선 지금 반복적으로 이야기하고 있죠? 이는 그만큼 토큰 기반 인증 시스템의 중요한 속성입니다. 토큰은 클라이언트사이드에 저장하기때문에 완전히 stateless 하며, 서버를 확장하기에 매우 적합한 환경을 제공합니다. 만약에 세션을 서버측에 저장하고 있고, 서버를 여러대를 사용하여 요청을 분산하였다면, 어떤 유저가 로그인 했을땐, 그 유저는 처음 로그인했었던 그 서버에만 요청을 보내도록 설정을 해야합니다. 하지만, 토큰을 사용한다면, 어떤 서버로 요청이 들어가던, 이제 상관이 없죠.
보안성
클라이언트가 서버에 요청을 보낼 때, 더 이상 쿠키를 전달하지 않음으로 쿠키를 사용함으로 인해 발생하는 취약점이 사라집니다. 하지만, 토큰을 사용하는 환경에서도 취약점이 존재 할 수 있으니 언제나 취약점에 대비해야 합니다
Extensibility (확장성)
여기서의 확장성은, Scalability 와는 또 다른 개념입니다. Scalability 는 서버를 확장하는걸 의미하는 반면, Extensibility 는 로그인 정보가 사용되는 분야를 확장하는것을 의미합니다. 토큰을 사용하여 다른 서비스에서도 권한을 공유 할 수 있습니다. 예를 들어서, 스타트업 구인구직 웹서비스인 로켓펀치에서는 Facebook, LinkedIn, GitHub, Google 계정으로 로그인을 할 수 있습니다. 토큰 기반 시스템에서는, 토큰에 선택적인 권한만 부여하여 발급을 할 수 있습니다 (예를들어서 로켓펀치에서 페이스북 계정으로 로그인을 했다면, 프로필 정보를 가져오는 권한은 있어도, 포스트를 작성 할 수 있는 권한은 없죠)
여러 플랫폼 및 도메인
서버 기반 인증 시스템의 문제점을 다룰 때 CORS 에 대하여 언급 했었죠? 어플리케이션과 서비스의 규모가 커지면, 우리는 여러 디바이스를 호환 시키고, 더 많은 종류의 서비스를 제공하게 됩니다. 토큰을 사용한다면, 그 어떤 디바이스에서도, 그 어떤 도메인에서도, 토큰만 유효하다면 요청이 정상적으로 처리 됩니다. 서버측에서 어플리케이션의 응답부분에 다음 헤더만 포함시켜주면 되지요.
Access-Control-Allow-Origin: *
이런 구조라면, assets 파일들(이미지, css, js, html 파일 등)은 모두 CDN 에서 제공을 하도록 하고, 서버측에서는 오직 API만 다루도록 하도록 설계 할 수도 있지요.
웹표준 기반
토큰 기반 인증 시스템의 구현체인 JWT는 웹 표준 RFC 7519 에 등록이 되어있습니다. 따라서 여러 환경에서 지원이 되며 (.NET, Ruby, Java, Node.js, Python, PHP …) 수많은 회사의 인프라스트럭쳐에서 사용 되고 있습니다 (구글, 마이크로소프트 …)
-출처