728x90

 

지난 포스팅에서는 토큰 기반 인증 시스템에 대해 알아보았다. 

 

JWT - 토큰 기반 인증

JWT에 대해 알아보기 전에, 모던 웹서비스에 많이 사용되고 있는 '토큰(Token) 기반 인증'에 대해 먼저 알아보자. API를 사용하는 웹서비스를 개발한다면, 토큰을 사용하여 유저들의 인증 작업을 처

dolphinsarah.tistory.com

 

이번 포스팅에서는, 토큰 기반 인증 시스템의 구현체인 JWT(JSON Web Token)에 대한 소개 후,

JWT 토큰의 기본 구조를 알아보자. 

 

 

JSON Web Token이란?

 

JSON Web Token(JWT)은 웹표준으로서, 두 개체에서 JSON 객체를 사용하여

가볍고 자가수용적인(self-contained) 방식으로 정보를 안정성 있게 전달해준다. 

 

  • 수많은 프로그래밍 언어에서 지원된다 - JWT는 C, Java, Python, C++, R, C#, PHP, JavaScript, Ruby, Go, Swift 등 대부분의 주류 프로그래밍 언어에서 지원된다.
  • 자가 수용적(self-contained)이다 - JWT는 필요한 모든 정보를 자체적으로 지니고 있다. JWT 시스템에서 발급된 토큰은, 토큰에 대한 기본 정보, 전달할 정보(로그인 시스템이라면 유저 정보), 그리고 토큰이 검증됐다는 것을 증명해주는 signature를 포함하고 있다. 
  • 쉽게 전달될 수 있다 - JWT는 자가수용적이므로, 두 개체 사이에서 손쉽게 전달될 수 있다. 웹서버의 경우 HTTP의 헤더에 넣어서 전달할 수도 있고, URL의 파라미터로 전달할 수도 있다. 

 

JWT는 어떤 상황에서 사용될까?

 

아래와 같은 상황에서 JWT가 유용하게 사용될 수 있다. 

 

회원 인증

JWT를 사용하는 가장 흔한 시나리오다. 

 

유저가 로그인을 하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달해준다. 

 

그 후, 유저가 서버에 요청을 할때마다 JWT를 포함하여 전달한다. 

 

서버가 클라이언트에게서 요청을 받을 때마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 

유저가 요청한 작업에 관한 권한이 있는지 확인하여 작업을 처리한다. 

 

서버에서는 유저의 세션을 유지할 필요가 없다. 

 

즉, 유저가 로그인되어 있는지 아닌지 신경쓸 필요가 없고, 유저가 요청을 했을 때 토큰만 확인하면 되기 때문에,

세션 관리가 필요 없어서 서버 자원을 많이 아낄 수 있다. 

 

정보 교류

JWT는 두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다. 

 

그 이유는, 정보가 sign 되어 있기 때문에 정보를 보낸이가 바뀌진 않았는지

정보가 도중에 조작되지는 않았는지 검증할 수 있다. 

 

 

JWT의 생김새 

 

JWT는 .을 구분자로 3가지의 문자열로 되어 있다. 구조는 아래와 같다. 

 

aaaaaa.bbbbbb.cccccc
헤더(header).내용(payload).서명(signature)

 

(JWT 토큰을 만들때는 JWT를 담당하는 라이브러리가 자동으로 인코딩 및 해싱 작업을 해준다.)

 

그럼 위와 같이 3가지 부분으로 나뉘어져 있는 각각에 대해 알아보자. 

 

헤더(Header)

헤더는 두 가지의 정보를 지니고 있다. 

 

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

 

정보(payload)

payload 부분에는 토큰에 담을 정보가 들어 있다. 

 

여기에 담는 '정보의 한 조각'클레임(claim)이라고 부른다. 

 

name/value의 한 쌍으로 이루어져 있다. 

 

그리고 토큰에는 여러 개의 클레임들을 넣을 수 있다. 

 

클레임은 등록된(registered) 클레임, 공개(public) 클레임, 비공개(private) 클레임으로 나뉘어져 있다. 

 

# 등록된(registered) 클레임

 

등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기 위해

이름이 이미 정해진 클레임들이다.

 

등록된 클레임의 사용은 모두 선택적(optional)이며, 이에 포함된 클레임 이름들은 다음과 같다. 

  • iss: 토큰 발급자(issuer)
  • sub: 토큰 제목(subject)
  • aud: 토큰 대상자(audience)
  • exp: 토큰의 만료시간(expiration). 시간은 NumericDate 형식으로 되어 있어야 하며(ex: 1480849147370), 언제나 현재 시간보다 이후로 설정되어 있어야 한다. 
  • nbf: Not Before를 의미. 토큰의 활성 날짜와 비슷한 개념. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않는다. 
  • iat: 토큰이 발급된 시간(issued at). 이 값을 사용하여 토큰의 age가 얼마나 되었는지 판단할 수 있다.
  • jti: JWT의 고유 식별자. 주로 중복 처리를 방지하기 위해 사용된다. 일회용 토큰에 사용하면 유용하다. 

 

# 공개(public) 클레임

 

공개 클레임들은 충돌이 방지된(collision-resistant) 이름을 가지고 있어야 한다. 

 

충돌을 방지하기 위해서, 클레임 이름을 아래와 같이 URI(Uniform Resource Identifier) 형식으로 짓는다. 

 

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

 

# 비공개(private) 클레임 

 

등록된 클레임도 아니고, 공개된 클레임도 아니다. 

 

양 측간에(보통 클라이언트 <-> 서버) 협의 하에 사용되는 클레임 이름이다. 

 

공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니, 사용할 때 유의해야 한다. 

 

{
    "username": "dolphinSarah"
}

 

아래 예제 payload는 2개의 등록된 클레임, 1개의 공개 클레임, 2개의 비공개 클레임으로 이루어져 있다. 

 

{
    "iss": "dolphinSarah.com",
    "exp": "1485270000000",
    "https://dolphinSarah.com/jwt_claims/is_admin": true,
    "userId": "11028373727102",
    "username": "dolphinSarah"
}

 

서명(signature)

JSON Web Token의 마지막 부분은 바로 서명(signature)이다. 

 

이 서명은 헤더의 인코딩 값과, 정보의 인코딩 값을 합친 후

주어진 비밀키로 해쉬를 하여 생성한다. 

 

서명 부분을 만드는 pseudo-code의 구조는 다음과 같다. 

 

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

 

이렇게 만든 해쉬를, base64 형태로 나타내면 된다. 

 

 

 

 

위 포스팅은 아래 링크를 참고하여 작성했습니다.

https://velopert.com/2389

728x90

'CS > 네트워크' 카테고리의 다른 글

HTTP 2.0과 특징  (0) 2021.06.11
로드밸런싱  (0) 2021.06.11
JWT - 토큰 기반 인증  (1) 2021.06.04
Authentication과 Authorization의 차이  (0) 2021.05.31
알아두면 좋은 HTTP X 헤더  (0) 2021.05.28
728x90

 

JWT에 대해 알아보기 전에, 모던 웹서비스에 많이 사용되고 있는 '토큰(Token) 기반 인증'에 대해 먼저 알아보자. 

 

API를 사용하는 웹서비스를 개발한다면, 토큰을 사용하여 유저들의 인증 작업을 처리하는 게 가장 좋다. 

 

토큰 기반 인증 시스템을 선택하는 것에는 여러가지 이유가 있다. 

그 중 주요 이유들은 아래와 같다. 

 

Stateless 서버

Stateless 서버를 이해하려면, Stateful 서버가 무엇인지 알아야 한다. 

Stateful 서버는 클라이언트에게서 요청을 받을 때마다, 클라이언트의 상태를 계속해서 유지하고, 이 정보를 서비스 제공에 이용한다. 

 

Stateful 서버의 예제로는 세션을 유지하는 웹서버가 있다. 

예를 들어 유저가 로그인을 하면, 세션에 로그인이 되었다고 저장을 하고,

서비스를 제공할 때 그 데이터를 사용한다. 

 

여기서 이 세션은, 서버컴퓨터의 메모리에 담을 때도 있고, 데이터베이스 시스템에 담을 때도 있다. 

 

반대로, Stateless 서버는 상태를 유지하지 않는다. 

상태 정보를 저장하지 않으면, 서버는 클라이언트 측에서 들어오는 요청으로만 작업을 처리한다. 

 

이렇게 상태가 없는 경우, 클라이언트와 서버의 연결고리가 없기 때문에 

서버의 확장성(Scalability)이 높아진다. 

 

모바일 어플리케이션에 적합하다

Android/ios 모바일 어플리케이션을 개발할 때, 안전한 API를 만들기 위해서 쿠키 같은 인증시스템은 이상적이지 않다. (쿠키 컨테이너를 사용해야 하기 때문에) 

 

토큰 기반 인증을 도입한다면, 더욱 간단하게 번거로움을 해결할 수 있다. 

 

인증 정보를 다른 어플리케이션으로 전달할 수 있다

대표적인 예제로, OAuth가 있다. 

페이스북/구글 같은 소셜 계정들을 이용하여 다른 웹서비스에서도 로그인할 수 있게 할 수 있다. 

 

보안

토큰 기반 인증 시스템을 사용하여 어플리케이션의 보안을 높일 수 있다. 

단, 이 토큰 기반 인증을 사용한다고 해서 무조건 해킹의 위험에서 벗어나는 건 아니다.

 

왜 토큰을 사용하게 되었을까?

 

토큰 기반 인증 시스템은 어떻게 나타나게 되었을까? 

이를 알아보기 위해서, 과거의 인증시스템이 어떤 방식으로 작동했는지 먼저 살펴보자.

 

서버 기반 인증

기존의 인증 시스템에서는 서버에서 유저들의 정보를 기억하고 있어야 한다. 

이 세션을 유지하기 위해서는 여러 방법이 사용된다. 

메모리 / 디스크 / 데이터베이스 시스템에 이를 담는다. 

 

서버 기반 인증 시스템의 흐름은 다음과 같다. 

 

서버 기반 인증 시스템의 흐름

 

이런 방식의 인증 시스템은 아직도 많이 사용되고 있다. 

하지만, 요즘 웹어플리케이션들이 부흥하면서, 이런 방식의 인증 시스템은 문제를 보이기 시작했다. 

예를 들면, 서버를 확장하기가 어렵다

 

서버 기반 인증의 문제점 

세션

: 유저가 인증을 할 때, 서버는 이 기록을 서버에 저장해야 한다. 이를 세션이라고 부른다.

대부분의 경우에는 메모리에 이를 저장하는데, 로그인 유저의 수가 늘어난다면 어떻게 될까?

서버의 램이 과부하될 것이다. 이를 피하기 위해, 세션을 데이터베이스 시스템에 저장하는 방식도 있지만, 

이 또한 유저의 수가 많으면 데이터베이스 성능에 무리를 줄 수 있다. 

 

확장성

: 세션을 사용하면 서버를 확장하는 것이 어려워진다. 여기서 서버의 확장이란, 

단순히 서버의 사양을 업그레이드 하는 것이 아니라 더 많은 트래픽을 감당하기 위해

여러 개의 프로세스를 돌리거나, 여러 대의 서버 컴퓨터를 추가하는 것을 의미한다.

세션을 사용하면서 분산된 시스템을 설계하는 게 불가능한 것은 아니지만, 과정이 매우 복잡해진다. 

 

CORS(Cross-Origin Resource Sharing)

: 웹 어플리케이션에서 세션을 관리할 때 자주 사용되는 쿠키단일 도메인 및 서브 도메인에서만 

작동하도록 설계되어 있다. 따라서, 쿠키를 여러 도메인에서 관리하는 것은 좀 번거롭다. 

 

토큰 기반 시스템의 작동원리

 

토큰 기반 시스템stateless하다. 즉, 상태 유지를 하지 않는다. 

이 시스템에서는 더 이상 유저의 인증 정보를 서버나 세션에 담아두지 않는다

 

이거 하나만으로도 위에서 서술한 서버에서 유저의 인증 정보를 서버측에 담아둠으로

발생하는 많은 문제점들이 해소된다. 

 

세션이 존재하지 않으니, 유저들이 로그인 되어있는지 아닌지 신경 쓰지 않으면서

서버를 손쉽게 확장할 수 있을 것이다. 

 

토큰 기반 시스템의 구현 방식은 시스템마다 크고 작은 차이가 있겠지만, 

대략 다음과 같다. 

 

  1. 유저가 아이디와 비밀번호로 로그인한다. 
  2. 서버에서 해당 계정 정보를 검증한다.
  3. 계정 정보가 정확하다면, 서버측에서 유저에게 signed 토큰을 발급해준다. (signed는, 해당 토큰이 서버에서 정상적으로 발급된 토큰임을 증명하는 signature를 지니고 있다는 뜻이다) 
  4. 클라이언트 측에서 전달받은 토큰을 저장해두고, 서버에 요청을 할때마다 해당 토큰을 서버에 함께 전달한다. 
  5. 서버토큰을 검증하고, 요청에 응답한다. 

토큰 기반 시스템의 구현 방식

 

웹서버에서 토큰을 서버에 전달할 때는, HTTP 요청의 헤더에 토큰 값을 포함시켜 전달한다. 

 

토큰의 장점

무상태(Stateless), 확장성(Scalability)

StatelessScalability는 토큰 기반 인증 시스템의 중요한 속성이다. 

토큰은 클라이언트사이드에 저장하기 때문에 완전히 stateless하며,

서버를 확장하기에 매우 적합한 환경을 제공한다. 

 

만약, 세션을 서버에 저장하고 있고, 서버를 여러 대 사용하여 요청을 분산했다면, 

어떤 유저가 로그인 했을 때, 그 유저는 처음 로그인했던 그 서버에만 요청을 보내도록 설정을 해야 한다. 

 

하지만, 토큰을 사용한다면 어떤 서버로 요청이 들어가든 상관 없다

 

보안성

클라이언트가 서버에 요청을 보낼 때, 더 이상 쿠키를 전달하지 않음으로

쿠키를 사용함으로 인해 발생하는 취약점이 사라진다

 

하지만, 토큰을 사용하는 환경에서도 취약점이 존재할 수 있으니,

언제나 취약점에 대비해야 한다. 

 

Extensibility(확장성)

여기서의 확장성은, Scalability와는 또 다른 개념이다. 

 

Scalability는 서버를 확장하는 걸 의미하지만, 

Extensibility로그인 정보가 사용되는 분야를 확장하는 것을 의미한다. 

 

토큰을 사용하여 다른 서비스에서도 권한을 공유할 수 있다. 

 

예를 들어, 로켓펀치에서는 Facebook, LinkedIn, GitHub, Google 계정으로 로그인할 수 있다. 

 

토큰 기반 시스템에서는, 토큰에 선택적인 권한만 부여하여 토큰을 발급할 수 있다.

(예를 들어, 로켓펀치에서 Facebook 계정으로 로그인을 했다면, 프로필 정보를 가져오는 권한은 있어도, 포스트를 작성할 수 있는 권한은 없다)  

 

여러 플랫폼 및 도메인

서버 기반 인증 시스템의 문제점 중 하나는 CORS이다. 

 

어플리케이션과 서비스의 규모가 커지면, 여러 디바이스를 호환시키고,

더 많은 종류의 서비스를 제공하게 된다.

 

토큰을 사용하면, 그 어떤 디바이스에서도, 그 어떤 도메인에서도, 

토큰만 유효하다면 요청이 정상적으로 처리된다. 

 

서버에서 어플리케이션의 응답 부분에 다음 헤더만 포함시켜주면 된다.

 

Access-Control-Allow-Origin: *

 

 

이번 포스트에서는 토큰 기반 인증 시스템과 기존의 시스템과 어떤 차이가 있는지 알아보았다. 

 

다음 포스트에서는 JWT에 대해 본격적으로 알아보도록 하자. 

 

 

위 포스팅은 아래 링크를 참고하여 작성했습니다. 

https://velopert.com/2350?openLinerExtension=true

 

 

728x90

'CS > 네트워크' 카테고리의 다른 글

로드밸런싱  (0) 2021.06.11
JWT - JSON Web Token  (0) 2021.06.04
Authentication과 Authorization의 차이  (0) 2021.05.31
알아두면 좋은 HTTP X 헤더  (0) 2021.05.28
알아두면 좋은 HTTP 쿠키, 캐시 헤더  (0) 2021.05.28
728x90

Authentication(인증)과 Authorization(인가)

 

누가, 언제, 어떻게 쓰고 있는가를 파악하기 위해 어떤 웹사이트든 Authentication(인증)Authorization(인가)가 있다. 

 

Authentication(인증)

  • 유저가 누구인지 확인하는 절차
  • 클라이언트가 자신이 주장하는 사용자와 같은 사용자인지를 확인하는 과정
  • 방문자가 자신이 회사 건물에 들어갈 수 있는지 확인받는 과정
  • ex) 회원가입, 로그인
  • 필요 이유: 서비스를 누가 사용하는지 추적이 가능하도록 하기 위해서. 타인에게 사용자의 정보를 보호하기 위해서. 

 

Authorization(인가)

  • 권한 부여
  • 클라이언트가 하고자 하는 작업이 해당 클라이언트에게 허가된 작업인지를 확인
  • 특정 자원에 대한 접근 권한이 있는지 확인하는 절차
  • 유저에 대한 권한을 허락하는 것
  • 방문자가 회사 건물에 방문했을 때, 허가된 공간에만 접근 가능

 

웹 인증(Authentication)

 

웹에서 인증을 요청하는 유저는 서버에게 두 가지 정보를 제시한다. 

  • 아이디 : 나는 '누구'이다. 
  • 비밀번호 : 내가 그 유저인 '증거'이다. 

 

HTTP 요청 방식

서버에 유저 정보를 보내서 사용 허가를 받는다. 

 

HTTP의 특징은 Request(요청)와 Response(응답)이다.

 

하지만, 이 방식에는 문제가 있다. 

 

통신을 서로 주고 받지만, 클라이언트와 서버가 서로 연결되어 있는 것은 아니기 때문에 

각각의 통신은 독립적이다. 

 

그리고, 한 번 요청과 응답이 완료되면 저장되지 않는 stateless 성질이 있다.

즉, 한 번 요청과 응답이 끝나면 상태 정보를 유지하지 않는다. 

 

그래서 다른 페이지로 넘어가면 정보가 없으므로, 인증 절차가 필요하다. 

 

HTTP 요청 인증 방식(쿠키, 세션, 토큰인증기반)

쿠키(Cookie)

  • 쿠키는 클라이언트(유저의 컴퓨터)에 저장되는 텍스트 형식의 데이터
  • 쿠키는 방문한 웹사이트에서 생성된 파일로, 인터넷 사용정보를 저장
  • 쿠키에는 사용자 인증이 유효한 시간을 명시할 수 있음
  • 한 번 유효 시간이 정해지면, 브라우저를 끄더라도 인증이 유지됨
  • ex) 방문 사이트에서 로그인 시, '아이디와 비밀번호를 저장하시겠습니까?'
  • ex) 쇼핑몰의 장바구니 기능

 

세션(Session)

  • 세션은 쿠키를 기반으로 함
  • 사용자 정보 파일을 브라우저에 저장하는 쿠키와 달리, 세션은 서버에서 관리
  • 세션 ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지함
  • 사용자에 대한 정보를 서버가 저장하기 때문에, 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다. 그래서 동접자 수가 많은 웹사이트의 경우 서버에 과부하를 주게 되므로 성능 저하의 요인이 된다. 

 

쿠키와 세션의 차이

  • 가장 큰 차이는 사용자의 기록 정보가 저장되는 위치
  • 쿠키는 서버의 자원을 전혀 사용하지 않고, 세션은 서버의 자원을 사용한다. 
  • 세션은 사용자 수만큼 서버 메모리를 차지하기 때문에, 요즘은 이런 문제를 보완한 토큰 기반의 인증 방식(JWT)을 사용하는 추세이다. 

 

토큰인증기반(JWT, Json Web Token)

  • JSON 데이터 구조로 표현한 토큰이다.
  • 서버에 정보를 보내고 결과를 JSON 형태 토큰으로 받는다. 
aaaaaa.bbbbbb.cccccc
헤더(header).내용(payload).서명(signature)

 

[JWT process]

이미지 참조) https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/

 

 

728x90

'CS > 네트워크' 카테고리의 다른 글

JWT - JSON Web Token  (0) 2021.06.04
JWT - 토큰 기반 인증  (1) 2021.06.04
알아두면 좋은 HTTP X 헤더  (0) 2021.05.28
알아두면 좋은 HTTP 쿠키, 캐시 헤더  (0) 2021.05.28
알아두면 좋은 HTTP 응답 헤더  (0) 2021.05.28

+ Recent posts