인증(Authorization)관련 Header, 그리고 쿠키(Cookie)

msung99·2022년 11월 7일
5
post-thumbnail

이번 포스팅에서는 HTTP 의 인증과 관련한 헤더와, 쿠키(Cookie) 에 대해서 알아보겠습니다. 특히 쿠키를 중점으로 알아볼텐데, 쿠키는 HTTP 의 Stateless 특성과 관련한 중요한 개념입니다.

HTTP Stateless 의 특성을 아직 잘 모르신다면 아래 제 포스팅을 참고하셔도 좋습니다.

https://velog.io/@msung99/HTTP

또 인증과 관련한 헤더는 크게 2가지가 있는데, Authorization 과 WWW-Authenticate 입니다.


Authorization

클라이언트의 인증 정보를 서버에 전달하는 헤더

인증 방법에는 정말 다양한 방식이 존재하는데, 각 방식마다 Authorization 에 들어가는 value 가 다릅니다. 그래서 각 인증 방식에 따라서 적절한 value 를 넣어주시면 됩니다.


WWW-Authenticate

리소스 접근시에 필요한 인증 방법을 정의하는 헤더

만일 접근을 시도했는데 인증이 잘 안된다면, 접근 권한 문제로 인해 401 Unauthorized 에러가 발생할 겁니다. 이 401 Unauthorized 응답이 발생할 때 이 헤더를 같이 넣어줘서 사용을 하면 됩니다.


쿠키(Cookie) 관련 Header

쿠키를 사용할 때는 다음과 같은 2개의 헤더를 사용합니다.

  • Set-Cookie : 서버에서 클라이언트로 쿠키를 전달(응답) 하는 헤더
  • Cookie : 클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청시 서버로 전달하는 헤더

이렇게만 본다면 쿠키가 무엇인지 잘 이해가 안되실겁니다. 쿠키가 뭔지 앞으로 계속 설명드리겠습니다.


로그인 이슈

로그인을 하는 상황을 가정해봅시다. 로그인 정보를 입력하고 POST 를 보내면 로그인이 될겁니다.
user 필드에 "홍길동" 이라는 정보를 인풋으로 넣어주면서 로그인을 하는 것이죠.

그런데, 로그인 이후에 welcome 페이지라는 곳에 접근한다고 생각해봅시다. 그러면 로그인 상태가 계속 유지될까요? 아닙니다. 저희는 로그인 상태가 계속 유지되길 기대하겠지만, HTTP 의 Stateless 특성상 서버가 계속 유저의 정보를 들고있는 방식이 아니기 때문에, 로그인을 시도했던 유저에 대한 정보를 계속 들고있지 못해서 마치 자동 로그아웃이 된 셈인거죠.

즉, 아래처럼 서버 입장에서는 이게 로그인한 사용자를 식별할 방법이 없습니다. 서버는 홍길동이란 사람이 보낸 GET 요청인지를 알 수가 없는겁니다.


Stateless 프로토콜의 특징

다시 HTTP 의 무상태(Stateless) 프로토콜의 특징에 대해 정리해 보고 넘어갑시다.

  • HTTP 는 무상태(Stateless) 프로토콜입니다.
  • 클라이언트와 서버가 요청과 응답을 주고 받으면 연결이 끊어집니다.
  • 클라이언트가 다시 요청하면 서버는 이전 요청을 기억하지 못합니다.
  • 클라이언트와 서버는 서로 상태를 유지하지 않습니다.

이렇듯 다시 로그인을 시도해도 서버에서는 이전 요청을 기억하고 있지 않기 때문에 문제가 발생하게 됩니다.


URL 에 유저 정보를 함께 넘겨주면 되는가?

그렇다면 모든 요청이 사용자 정보를 포함해서 보내면 되는 방식을 생각해볼 수 있습니다.

/welcome 페이지에 요청을 보낼때, 계속 URL의 user 파라미터에 홍길동이라는 값을 계속해서 포함해서 요청을 보내는것이죠.

그런데 이런 방식에는 문제가 있습니다. 모든 요청의 URL 에 사용자 정보(ex. 유저 pk값, 비밀번호 등)를 포함시켜서 요청을 보내는 방식입니다. 즉, 보안성에 문제가 발생해서 결코 좋은 방식이 아닙니다.


쿠키(Cookie) : 무상태 프로토콜의 대안

이래서 등장한 개념이 바로 쿠키(Cookie) 입니다.

첫 로그인 시도 : 쿠키 생성

웹 브라우저가에서 POST 요청을 통해 user 정보를 넘겨주면서 로그인을 시도하면, 서버는 쿠키(Cookie) 를 생성하고 그 안에 유저에 대한 정보를 넣습니다. 그러고 Set-cookie 헤더에 쿠기를 실어서 클라이언트에 리턴하는 방식입니다.

그러면 웹 브라우저 내부에는 쿠키 저장소가 있는데, 이 저장소에 user=홍길동 이라는 홍길동 유저에 대한 key-value 데이터를 저장합니다. 즉, 서버에서 만든 쿠키에 들어있는 유저의 key-value 데이터를 저장하는 것입니다.

로그인 이후에 유저 정보 꺼내오기

로그인 이후에 웹브라우저의 /welcome 페이지에 접근하는 상황을 생각해봅시다.
그러면 로그인 이후에는 웹브라우저는 서버에 요청을 보낼때마다, 요청을 보내기 직전에 자동으로 쿠키 저장소를 무조건 뒤져서 쿠키 key-value 데이터를 꺼내옵니다.

꺼내온 쿠키 데이터를 기반으로 Cookie HTTP 헤더를 만들어서 서버에 요청에 함께 실어서 보냅니다. 그러면 서버 입장에서는 로그인한 유저가 어떤 사람인지를 인식할 수 있게 됩니다.

이로써 지저분하게 URL 에 query parameter 로 유저의 정보를 넣어줘야하는 번거로움이 없어졌습니다.

정리를 해보면 아래와 같습니다.

    1. 첫 로그인 시도를 위해 POST 요청을 서버에 보내면, 서버는 키를 생성하고 그 안에 유저 정보를 실어서 Set-cookie 헤더로 포장해서, 쿠키 스토리지(Storage) 에 쿠키를 저장

    1. 로그인 이후, 아무 웹 페이지에 요청을 시도하면 쿠키 스토리지에 저장된 쿠키(현재 로그인한 유저 정보)를 꺼내옴

    1. 꺼내온 쿠키를 Cookie 라는 HTTP 헤더에 실어서 서버에 요청을 전송

    1. 서버는 Cookie 헤더에 들어있는 유저 정보를 읽고 로그인한 유저가 누구인지를 식별한다.

쿠키의 구성성분

쿠키는 아래와 같은 성분들로 구성됩니다.

  • sessionId : 유저 정보에 대해 보완성을 강화한 데이터 정보 (쿠키에 유저 정보를 직접적으로 저장하지 않기위함)
  • expires : 만료기간. 즉 쿠키의 유효기간으로, 유효기간이 다되면 쿠키가 삭제된다.
  • path : 경로 (쿠키가 전달되고 접근 가능한 경로를 지정가능)
  • domain : 도메인 (쿠키가 전달되고 접근 가능한 도메인을 지정가능)
  • Secure : 보안관련 옵션

또한 쿠키의 형태는 보통 아래와 같습니다.

set-cookie: sessionId=abcde1234; expires=Sat 26-Dec-2020 00:00:00 GMT; path=/; domain=google.com; Secure

쿠키의 보안성

쿠키는 웹 페이지에서 실행되는 모든 요청에 대해 쿠키 정보를 자동으로 포함시킵니다.

  • 클라이언트에서 요청을 /welcome, /board, /order, ... 등 그 어떠한 페이지로 보내도 쿠키의 데이터를 쿠키 스토리로 부터 무조건 뽑아와서 요청에 실어서 함께 보내줍니다.

=> 그렇다면, 모든 요청에 쿠키를 실어서 보낸다면 보안에 문제가 발생하지 않을까요? 그래서 이를 제약하는 방법이 존재합니다. 그것은 바로 "세션(Session)" 이니다.


쿠키의 세션관리 : SessionId

쿠키의 주 사용처는 사용자 로그인 세션을 관리할때 자주 사용됩니다.
만일 위처럼 Set-Cookie 에 그대로 user에다 홍길동을 정보를 그대로 실어서 보내고, 활용하는 것은 보안성에 있어 위험한 일입니다.

서버는 로그인에 성공하면 Session Key(세션 키) 라는 것을 따로 발급해줍니다.
발급한 세션키를 어떤 DB 에 저장해두고, 이 세션키를 SessionId 라는 곳에 실어서 클라이언트에게 반환해줍니다.

그러면 클라이언트는 서버에 요청을 보낼때마다 SessionId 를 보내고, 서버는 요청으로 받은 헤더에 SessionId 를 열어보고 어떤 유저인지를 식별하는 방식입니다.


쿠키의 특징

쿠키의 정보는 항상 요청을 보낼때 마다 서버에 전송되기 떄문에, 네트워크 트래픽이 추가적으로 발생합니다.

  1. 따라서 쿠키에는 최소한의 정보만 저장하고 사용하는 것이 좋습니다.
    예를들어 세션id (SessionId), 인증 토큰(token) 만 사용합시다.
  • 세션 id 란 앞서 살펴봤듯이, 로그인을 하면 서버에서 자동으로 발급해주는 유저 정보입니다.
  • 토큰(Token) 은 Auth 를 사용하면 발급됩니다.

쿠키처럼 서버에 전송하지 않, 웹 브라우저 내부에 데이터를 저장하고 싶다면 웹 스토리지(localStorage, sessionStorage) 를 사용합시다.

  • 쿠키처럼 서버에 요청할떄 마다 보내는 방식이 아닌, 클라이언트에서 유저 정보를 계속 들고 싶은 경우 웹 스토리지(localStorage, sessionStorage) 라는 것을 사용하면 됩니다.

쿠키의 생명주기 (Expires)

쿠키는 스토리지에 무제한 기간으로 저장할 수는 없을겁니다. 즉 쿠키에는 만료기간(Expires date)이 존재합니다. 쿠키의 만료일을 지정할 수 있는 옵션은 2가지가 존재합니다.

쿠키의 만료기간(Expire Dates) 지정 옵션

  • expires
  • max-age

expires

Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT

예를들어 발급받은 쿠키에 대해 만료기간을 설정하려면 expires 옵션으로 날짜의 형태로 만료기간을 부여할 수 있습니다.
그리고 만료일이 되면 쿠키는 삭제가 됩니다.

max-age

Set-cookie: max-age=3600     // (=> 3600초)

초 단위로 만료기간을 설정하는 옵션입니다. 이때 0이나 음수로 지정하면 쿠키가 삭제됩니다. 그리고 당연히 만료기간이 지나도 쿠키가 삭제될겁니다.


쿠키의 종류

쿠키의 생명주기를 어떻게 부여하는가에 따라서 쿠키의 종류가 달라집니다.

세션쿠키

그리고 쿠키에 세션쿠키와 영속쿠키라는 것이 존재합니다. 세션쿠키는 만료 날짜를 생략하면 브라우저 종료시 까지만 유지되는 쿠키입니다.

=> 웹 브라우저 중에서 브라우저를 닫고 다시 열면, 또 다시 로그인해야하는 브라우저들이 세션 쿠키를 사용하는 경우 입니다.

영속쿠키

영속 쿠키는 만료 날짜를 입력하면 해당 날짜까지 유지되는 쿠키입니다.


쿠키의 도메인(Domain)

쿠키에 도메인을 지정해서, 지정해준 특정 도메인에만 쿠키에 전달되고 접근할 수 있습니다.

쿠키가 아무 사이트에 들어갈 때 마다 계속 생기면 보안성에 문제가 발생할 겁니다. 그래서 원하는 도메인에서만 쿠키가 생성되도록 도메인을 지정해줄 수 있습니다.

도메인을 지정하는 방법을 2가지입니다. 명시적으로 도메인을 지정해주거나, 도메인을 생략하는 방법입니다.

1. 도메인을 명시한 경우

  • 도메인을 명시하게 되면, 명시한 문서 기준 도메인과 + 서브 도메인에서 모두 쿠키에 접근 가능합니다.

예를들어 domain=exmaple.org 를 지정하면,
example.org 에서 쿠키가 생성되고, example.org 와 그의 서브도메인인 dev.example.org 에서 모두 해당 쿠키가 전달될 수 있고 접근 가능합니다.

2. 도메인을 생략한 경우

  • 반면 도메인을 생략한다면, 현재 문서 기준 도메인에서만 쿠키에 접근 가능합니다.

exmaple.org 에서 쿠키를 생성하고, domain 은 생략했다면
example.org 에서만 해당 쿠키가 전달될 수 있고 접근가능합니다. 또 dev.example.org 서브 도메인에서는 쿠키에 접근이 불가능합니다.


쿠키의 경로(path)

쿠키에는 경로도 지정해줄 수 있습니다.

경로를 지정하면, 지정해준 해당 경롤를 포함한 하위 경로 페이지에만 쿠키로 접근할 수 있습니다.

  • 일반적인 형태 : "path=/ 루트경로"

ex) 예를들어 path 에다 "path=/home" 과 같이 지정한경우,
home 디렉토리를 포함한 그의 하위 디렉토리에서 모두 쿠키가 전달이 됩니다.

즉, /home, /home/sub_home1 등의 디렉토리에는 쿠키가 전달이 되지만,
/other_home 디렉토리는 쿠키가 전달이 되지 않습니다.


쿠키의 보안(Secure, HttpOnly, SameSite)

마지막으로 쿠키에 보안과 관련한 3가지 옵션도 지정가능합니다.

Secure

쿠키는 기본적으로 http 와 https를 별도로 구분하지 않고 전송되는 방식이지만, Secure 옵션을 적용하면 https 인 경우에만 쿠키가 전송됩니다.

HttpOnly

XSS 공격을 방지할 수 있게 합니다. 원래는 자바스크립트에서 document.cookie 를 통해 쿠키에 접근 가능하나, 이 옵션을 적용하면 접근이 불가능해집니다.

대신에 HTTP 전송에서만 사용할 수 있는 옵션입니다.

SameSite

XSRF 공격을 방지할 수 있게 합니다.
(이 내용은 깊은 보안과 관련한 내용으로, 추가적으로 검색해보시면 좋겠습니다.)

1개의 댓글

comment-user-thumbnail
2023년 11월 14일

좋은 글 너무 감사합니다!

답글 달기