관리 메뉴

Jerry

인증 #3 (쿠키, 세션, 토큰) 본문

Authentication

인증 #3 (쿠키, 세션, 토큰)

juicyjerry 2021. 5. 11. 16:20
반응형

오늘은 토큰에 대해서 알아보는 시간이다.

 


 

 

 

모던 웹서비스에서 토큰 기반 인증은 많이 사용되고 있으며 api를 사용하는 웹서비스 개발한다면,

토큰을 사용하여 유저 인증 작업을 처리하는 것이 가장 좋다고 합니다. 왜 그럴까요?

 

첫 번째, stateless 서버입니다. stateful의 반대말로, 서버는 클라이언트에게서 요청받을 때마다, 클라이언트의 상태를 계속 유지하고, 이 정보를 서비스 제공에 이용합니다. stateful 서버의 예로 세션을 유지하는 웹서버가 있습니다.

 

statless 서버는 클라이언트 요청으로만 작업을 처리하지 상태를 유지하지 않습니다. 이렇게 되면, 클라이언트와 서버와 연결고리가 없기 때문에 서버의 확장성(Scalability)이 높아집니다.

 

둘째, 모바일 애플리케이션에 적합입니다. 안전한 api를 만들기 위해 토큰 기반 인증을 도입할 수 있습니다.

 

셋째, 인증정보를 다른 애플리케이션으로 전달입니다. OAuth로 소셜 계정을 이용한 다른 웹서비스에 로그인할 수 있습니다.

 

넷째, 보안입니다. 토큰 기반 인증 시스템을 사용함으로써 애플리케이션 보안을 높일 수 있습니다. (무적x)

 

 

 

 

토큰을 사용하게 된 이유

과거, 서버 기반 인증 시스템은 서버 측에서 유저 정보를 기억하기 위해서(세션 유지) 메모리 / 디스크 / 데이터베이스 시스템을 이용했습니다. 

 

 

 

이런 방식은 아직도 사용하고 있지만, 요즘 웹 / 앱 애플리케이션 부흥하게 되면서, 문제점을 보였습니다.

1. 세션에 저장해야 할 정보가 많아져 서버에 과부하가 된다면 혹은 점점 유저가 많아진다면 세션 성능에 (세션을 데이터베이스에 저장한다면) 데이터베이스 성능에 무리가 갈 수 있습니다.

 

2.  더 많은 트래픽을 감당하기 위해 여러 프로세스를 돌리거나, 여러 대의 서버 컴퓨터 추가를 '서버의 확장'이라고 합니다. 세션을 사용하면 확장하기가 매우 복잡해진다고 합니다.

 

3. 세션과 짝꿍인 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어(CORS), 여러 도메인에서 관리하기 번거로울 수 있습니다. 

 

 

 

 

 

토큰 기반 시스템 작동 원리

유저가 로그인하게 되면, 서버 측에서 계정 정보를 검증하여, 정확하면 유저에게 signed 토큰을 발급합니다.

이후, 클라이언트 측에서 저장을 해두고, 서버 요청 시에 (HTTP Request header에 토큰 값을 넣어) 토큰을 서버에 전달하며, 서버는 검증 / 응답하는 과정을 거칩니다.

 

 

 

 

 

 

 

 

토큰의 장점

1. 무상태성(statless) / 2. 확장성(stablility) / 3. 보안성 / 4. Extensibility(확장성)

1. 토큰은 클라이언트 측에 저장되기에 stateless 하며 서버 확장에 용이합니다.

2. 세션-쿠키를 사용하지 않아 보완성이 유지됩니다.

3. 로그인 정보가 사용되는 분야가 확장됩니다. (sns 계정으로 다른 웹서비스 로그인이 가능)

4. 어떤 디바이스에서도, 어떤 도메인에서도, 토큰만 유효하다면, 요청 정상 처리됩니다. (서버에서 Access-Control-Allow-Origin: *처리해줘야 함)

 

 

JWT

JSON WEB TOKEN의 줄임말이자, JWT토큰 기반 인증 시스템 구현체 JWT는 웹 표준에 등록되어 여러 환경에서 지원되며 수많은 회사 인프라스트럭쳐에 사용되고 있습니다. 자가 수용적 (self-contained) 특성으로, 필요한 모든 정보를 지니고 있습니다(기본정보, 전달할 정보, 검증 여부 증명해주는 signature). 이런 자가 수용적 특성으로 HTTP 헤더에 넣어 전달되거나 URL 파라미터로 손쉽게 전달할 수 있습니다.

 

이런 JWT는 회원 인증에서 사용되거나 정보 교류 용도로 사용할 수 있습니다. 

 

JWT 생김새

. 을 구분자로 3가지 문자열로 구성됩니다. (헤더. 내용. 서명)

 

 

 

 

 

 

헤더(heaer)는 typ, alg 정보를 가지고 있습니다. 

typ은 토큰 타입으로 JWT이며, alg는 해싱 알고리즘을 지정합니다.
(보통, HMAC SHA256 혹은 RSA가 사용되며, 토큰 검증할 때 사용되는 signature 부분에서 사용)

 

const header = {
  "typ": "JWT",
  "alg": "HS256"
};

// encode to base64
const encodedPayload = new Buffer(JSON.stringify(payload))
                            .toString('base64')
                            .replace('=', '');
console.log('payload: ',encodedPayload);

/* Result:
header: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
*/

 

 

정보(payload)에는 토큰 정보가 들어있습니다. 정보의 한 조각을 클레임(claim)이라 부르고, name / value 한쌍으로 이뤄져 있습니다. 클레임은 1. 등록된 (registered) / 2. 공개 (public) / 3. 비공개(private) 클레임으로 나뉩니다.

 

1번은 서비스에서 필요한 정보가 아닌, 토큰에 대한 정보를 담기 위해 이름이 이미 정해진 클레임

2번은 공개되었으며, 충돌 방지를 위해 url 형식으로 지어진 이름

{
    "https://velopert.com/jwt_claims/is_admin": true
}

3번은 등록되지도 않았고, 공개되지도 않은 클레임이며 이름 충돌 방지가 될 수 있으니 유의해야 함

{
    "username": "velopert"
}

 

 

서명(signature)은 헤더의 인코딩 값과 정보의 인코딩 값을 합친 후 주어진 비밀키로 해쉬를 하여 생성합니다. 

 

 

 

 

 

 

출처: 

velopert | velopert.com/2389

velopert | velopert.com/2350

 

 

 

 

반응형

'Authentication' 카테고리의 다른 글

인증 #2 (쿠키, 세션, 토큰)  (0) 2021.05.10
인증 #1 (쿠키, 세션, 토큰)  (1) 2021.05.07