HTTP의 인증에 대해 (1) 인증의 발전사

이 시리즈에서는 HTTP의 인증(Authentication)에 대해 다룹니다.

이번 글에서는 HTTP의 인증이 어떤 방식으로 발전되어 왔으며, JWT가 뭐고 무엇인지를 다루도록 하겠습니다.

목차

인증(Authentication)과 인가(Authorization)?

헷갈리기 쉬운 인증과 인가부터 짚고 넘어가도록 하겠습니다.

1. HTTP의 초창기 인증

데이터를 받아보는 당신이 누구인지를 묻는 요구사항은 HTTP/1.0 스펙부터 등장하였습니다[1]. 1996년부터 등장했고 현재는 사용하지 않습니다. 다만 어떤식으로 발전했는지를 살펴봅시다.

BASIC 인증

Authorization: "Basic dXNlcjpwYXNz"

Digest 인증

  1. 보호된 영역에 접속하려할 때, 401 Unauthorized를 받고, 서버로부터 특정 값을 받습니다(handle_401 호출).

    1. WWW-Authenticate: Digest realm="영역명", nonce="임의의값", algorithm="알고리즘명", qop="auth"
      1. 접근하고자 하는 영역(realm)
      2. 서버에서 무작위로 생성하는 데이터(nonce)
      3. 서버의 보호수준 (qop)
      4. nonce를 통해 호출한 횟수 (nc)
  2. 유저는(사실은 유저의 클라이언트죠) A1, A2와, 무작위로 생성한 cnonce 라는 값을 토대로 response를 계산합니다(build_digest_header).

    1. A1: 유저명 ":" realm ":" 패스워드
    2. A2: HTTP 메소드 ":" 컨텐츠 URI
    3. response: MD5(MD5(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" MD5(A2))
  3. 서버측은 자신이 가진 유저명/패스워드와 위 과정에서 받은 정보를 가지고 "동일한"response를 계산하게 되면, 인증에 성공하게 됩니다.

옛 인증의 한계점

이런 인증을 현대에 대응하기에는 무리가 있습니다. 이유는 아래와 같습니다.

  1. 요청/응답마다 매번 연산하는 것이 부담입니다.
  2. 로그인 화면을 사용자화 하기 어렵습니다.
  3. 명시적 로그오프 명령을 내리기 어렵습니다.
  4. 로그인한 유저를 식별할 수 없습니다.

이러한 사항 때문에, HTML의 Form을 이용한 로그인과, 쿠키를 이용한 세션관리 조합으로 발달되게 되었습니다.

2. 쿠키와 세션을 사용한 인증

현대에까지 널리 사용되고 있는 브라우저 쿠키와 세션을 통한 인증이 있곘습니다. 아래에서 기본적인 개념을 살펴보겠습니다.

쿠키와 세션을 이용한 인증

장고에서는?

여러 방법이 있겠습니다만, 장고에서 세션을 활용하는 방안은 여러가지가 있습니다.

세션을 어떤 식으로 관리할지에 대한 설정은 아래와 같습니다:

Django REST Framework 에서는?

3. JWT(JSON Web Token)의 등장

이어서 JWT입니다. 우선은 간략하게 JWT가 무엇인지 살펴보겠습니다.

JWT란?

JSON Web Token(JWT)는 2010년 10월 28일, 처음 발표되었습니다. 간략한 정보는 아래와 같습니다.

소개는 이쯤하고, 구조를 먼저 살펴본 후 사용례를 살펴봅시다.

구조

JWT의 구조를 살펴봅시다. JWT는 헤더.페이로드.시그니처 의 세 부분으로 구성됩니다. .은 구분자로 사용됩니다.

JWT는 이런 모양을 가집니다.

aaaaa.bbbbb.ccccc

보다 정확한 스펙은 상술한 RFC 문서를 참고해주세요.

헤더

{
  "alg": "HS256",
  "typ": "JWT"
}

페이로드

(!) claim: JWT에 의해 전달된 개별 값들이 구성원인 JSON 개체를 나타냅니다.

{
  "sub": "1",
  "name": "s3ich4n",
  "admin": false
}

시그니처

토큰이 유효한지 검증합니다. 시그니처는 RFC 4648(Base64Url)을 사용하여 헤더와 페이로드를 인코딩하기위해 계산됩니다. 그리고 구분자 .을 이용하여 둘을(헤더, 페이로드) 합칩니다. 이후 공개키/비밀키(RSA나 ECDSA 등)나 shared secrets값(HAMC)을 통해 시그니처를 생성합니다.

예를들어 HMAC SHA-256 알고리즘을 사용한다면, 시그니처는 아래와 같이 생성됩니다.

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

세 값을 모두 합치면?

이런 모양이 나옵니다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI

마무리

이번 글을 통해, 아래 내용들을 살펴볼 수 있었습니다:

  1. HTTP 상에서의 인증에 대해 Basic 부터 쿠키와 세션, JWT에 이르기까지를 간략히 살펴볼 수 있었습니다.
  2. JWT가 무슨 목적으로 만들어졌으며, 어떤 구조로 이루어져 있는지 간략히 알 수 있었습니다.

다음 글에서는 JWT가 어떤식으로 인증(및 인가)에 쓰이게 되는지, JWT의 특성을 오해하고 잘못 사용중인건 아닌지 살펴보겠습니다.

읽어주셔서 감사합니다.


  1. 해당 링크를 참고해주세요. ↩︎