[정리] 쉽게 알아보는 서버 인증 1편

GreenBean·2022년 1월 12일
0
post-thumbnail

서버 인증

정리 원본 링크 : 쉽게 알아보는 서버 인증 1편

인증이 필요한 이유

  • 사용자 A와 사용자 B가 앱을 사용한다고 가정했을 때, 두 사용자는 기본적으로 정보가 다르고 보유하고 있는 컨텐츠도 다름
  • 따라서 서버에서는 A와 B가 요청을 보냈을 때 누구의 요청인지를 정확히 알아야 함
    • 만일 그렇지 못한다면, 사용자의 정보가 타인에게 유출되는 최악의 상황이 발생
    • 그렇기에 앱(프론트엔드)에서는 자신이 누구인지를 알만한 단서를 서버에 보내야 하며, 서버는 그 단서를 파악해 각 요청에 맞는 데이터를 뿌려줘야 함

HTTP 요청

  • 현재 모바일이나 웹 서비스에서 가장 많이 쓰이는 통신 방식은 HTTP 통신
  • HTTP 통신응답 후 연결을 끊게 되며 과거에 대한 정보를 전혀 담고 있지 않음
    • 이 말은 지금 보낼 HTTP 요청은 지난 번에 내 정보를 담아 보냈던 HTTP 요청과 전혀 관계가 없다는 뜻
    • 따라서 각각의 HTTP 요청에는 주체가 누구인지에 대한 정보가 필수적
  • 서버에 요청을 보내는 작업HTTP 메세지를 보내는 것
    • HTTP 메세지의 구조는 일반적으로 헤더와 바디 두가지로 구성되며, 공백은 헤더와 바디를 구분짓는 역할을 함
    • 여기서 헤더에는 기본적으로 요청에 대한 정보들이 들어가며, 바디에는 서버로 보내야할 데이터가 들어가게 됨
    • 보통 모바일•웹 서비스의 인증HTTP 메세지의 헤더에 인증 수단을 넣어 요청을 보내게 됨

Tip! HTTP의 특징

  • 클라이언트 서버 구조
    • 클라이언트가 서버에 요청을 보내면 서버는 그에 대한 응답을 보내는 클라이언트 서버 구조
  • 무상태 프로토콜 (Stateless)
    • HTTP에서 서버가 클라이언트의 상태를 보존하지 않는 무상태 프로토콜
  • 비 연결성 (Connectionless)
    • HTTP 1.0 기준으로 HTTP는 연결을 유지하지 않는 모델

인증 방식

1. 계정 정보를 요청 헤더에 넣는 방식

  • 가장 보안이 낮은 방식계정 정보를 요청에 담아 보내는 방식
    • 위에서 언급한 HTTP 요청에 인증할 수단에 비밀번호를 넣는 방법
      • 최악의 인증방식
      • 데이터를 요청할 때마다 사용자의 프라이빗한 정보를 계속해서 보낸다는 건 보안에 상당히 좋지 않음
    • 보통 앱에서는 서버로 HTTP 요청을 할 때 따로 암호화되지 않기 때문에 해커가 마음만 먹으면 HTTP 요청을 가로채서 사용자의 계정 정보를 알 수 있음
    • 본 방식은 절대로 실제 서비스에서는 쓰이지 않음
      • HTTP 요청을 암호화해서 보안을 높이는 방식으로 HTTPS가 있지만 그렇다고 해도 쓰이지 않음
  • 장점
    • ❶ 인증을 테스트 할 때 빠르게 시도 가능
  • 단점
    • ❶ 보안에 매우 취약
    • ❷ 서버에서는 신호가 올 때마다 ID와 PW를 통해 유저가 맞는지 인증해야 하는데 이는 비효율적

2. 세션(Session) 쿠키(Cookie) 방식

  • 계정 정보를 매번 요청에 넣어서 보내기엔 보안에 너무 취약하기 때문에 나온 인증 방법이 세션 쿠키 방식

  • 순서
    • ① 사용자가 로그인 함
    • ② 서버에서는 계정 정보를 읽어 사용자를 확인한 후, 사용자의 고유한 ID값을 부여하여 세션 저장소에 저장하고 이와 연결되는 세션 ID를 발행
    • ③ 사용자는 서버에서 해당 세션 ID를 받아 쿠키에 저장을 한 후, 인증이 필요한 요청마다 쿠키를 헤더에 실어 보냄
    • ④ 서버에서는 쿠키를 받아 세션 저장소에서 대조를 한 후 대응되는 정보를 가져옴
    • ⑤ 인증이 완료되고 서버는 사용자에 맞는 데이터를 보내줌
  • 세션 쿠키 방식의 인증은 기본적으로 세션 저장소를 필요로 함
    • 일반적으로 레디스(Redis)를 많이 사용
  • 세션 저장소는 로그인을 했을 때 사용자의 정보를 저장하고 열쇠가 되는 세션 ID값을 생성하고 HTTP 헤더에 실어 사용자에게 돌려보냄
  • 그러면 사용자는 받은 세션 ID값을 쿠키에 보관하고 있다가 인증이 필요한 요청에 쿠키를 넣어 보냄
  • 웹 서버에서는 세션 저장소를 통해 받은 쿠키의 세션 ID값과 저장되어 있는 정보를 매칭시켜 인증을 완료

Tip!

  • 세션 ID쿠키라고 봐도 동일
    • 쿠키가 사용자 개념에서 더 큰 범주
    • 세션 ID를 쿠키로 저장하는 셈

Tip!

  • 세션서버에서 가지고 있는 정보이며 쿠키사용자에게 발급된 세션을 열기 위한 열쇠(세션 ID)를 의미
    • 쿠키만으로 인증을 한다는 것은 서버의 자원은 사용하지 않는다는 뜻으로, 이 때는 클라이언트가 인증 정보를 책임지게 됨
    • 그렇게 되면 위의 첫번째 방식처럼 HTTP 요청을 탈취당할 경우 다 털리게 됨
      • 따라서 보안과는 상관 없는 단순한 장바구니나 자동 로그인 설정 같은 경우에만 쓰이고 있음
    • 결과적으로 인증의 책임을 서버가 지도록 하기 위해 세션을 사용
      • 사용자가 해킹당하는 것보단 서버가 해킹당하는게 훨씬 어렵기 때문
    • 사용자(클라이언트)는 쿠키를 이용하고 서버에서는 쿠키를 받아 세션의 정보를 접근하는 방식으로 인증을 함
  • 장점
    • ❶ 세션 쿠키 방식은 기본적으로 쿠키를 매개로 인증을 거치는데 여기서 쿠키는 세션 저장소에 담긴 유저 정보를 얻기 위한 열쇠라고 보면 됨
      • 따라서 쿠키가 담긴 HTTP 요청이 도중에 노출되더라도 쿠키 자체(세션 ID)는 유의미한 값을 갖고 있지 않기 때문에 이는 위의 계정정보를 담아 인증을 거치는 것보단 안전
      • 중요 정보는 서버 세션에 존재
    • ❷ 사용자들은 각각 고유한 ID값을 발급받게 되는데 그렇게 되면 서버에서는 쿠키 값을 받았을 때 일일이 회원 정보를 확인할 필요 없이 바로 어떤 회원인지를 확인할 수 있어 서버의 자원에 접근하기 용이
  • 단점
    • ❶ 쿠키를 탈취당하더라도 안전할 수 있다고 언급했지만 문제는 존재
      • 만일 A 사용자의 HTTP 요청을 B 사용자(해커)가 가로챘다면 그 안에 들어있는 쿠키도 충분히 훔칠 수 있으며, B 사용자가 그 훔친 쿠키를 이용해 HTTP 요청을 보내면 서버의 세션 저장소에서는 A 사용자로 오인해 정보를 잘못 뿌려주게 됨
      • 세션 하이재킹 공격이라고 함
    • 해결책
      • HTTPS를 사용해 요청 자체를 탈취해도 안의 정보를 읽기 어렵도록 만듬
      • 세션에 유효시간을 넣어줌
    • ❷ 서버에서 세션 저장소를 사용하기 때문에 추가적인 저장 공간을 필요로 하게 되고 자연스럽게 서버의 부하도 높아짐

3. 토큰 기반 인증 방식 (JWT)

  • JWT는 세션 쿠키 방식과 함께 모바일과 웹의 인증을 책임지는 대표 주자
    • JWT는 Json Web Token의 약자로 인증에 필요한 정보들을 암호화시킨 토큰을 뜻함
    • 위의 세션 쿠키 방식과 유사하게 사용자는 Access Token(JWT 토큰)을 HTTP 헤더에 실어 서버로 보내게 됨

  • JWT 토큰을 만들기 위해서는 Header, Payload, Verify Signature 크게 3가지가 필요
    • Header : 정보를 암호화할 방식(alg), 타입(type) 등이 들어감
    • Payload : 서버에서 보낼 데이터가 들어가며 일반적으로 유저의 고유 ID값, 유효 기간이 들어감
    • Verify Signature : Base64 방식으로 인코딩한 Header, payload 그리고 SECRET KEY를 더한 후 서명됨
  • 최종적인 결과 : Encoded Header + "." + Encoded Payload + "." + Verify Signature
    • Header, Payload는 16진수로 인코딩될 뿐 따로 암호화되지 않기 때문에 JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있음
    • 누구나 디코딩할 수 있다는 말은 Payload에 유저의 중요한 정보가 들어가면 쉽게 노출될 수 있다는 말이 됨
    • 하지만 Verify SignatureSECRET KEY를 알지 못하면 복호화할 수 없음
      • A 사용자가 토큰을 조작하여 B 사용자의 데이터를 훔쳐보고 싶다고 가정했을 때
        • Payload에 있던 A의 ID를 B의 ID로 바꿔서 다시 인코딩한 후 토큰을 서버로 보냄
        • 서버는 암호화된 Verify Signature를 검사함
        • 여기서 Payload는 B 사용자의 정보가 들어가 있으나 Verify Signature는 A의 Payload를 기반으로 암호화되었기 때문에 유효하지 않는 토큰으로 간주하게 됨
        • 여기서 A 사용자는 SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없다는 걸 확인할 수 있음

  • 순서
    • ① 사용자가 로그인 함
    • ② 서버에서는 계정 정보를 읽어 사용자를 확인 후, 사용자의 고유한 ID값을 부여하여 기타 정보와 함께 Payload에 넣음
    • ③ JWT 토큰의 유효 기간을 설정
    • ④ 암호화할 SECRET KEY를 이용해 Access Token을 발급
    • ⑤ 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보냄
    • ⑥ 서버에서는 해당 토큰의 Verify SignatureSECRET KEY로 복호화한 후, 조작 여부와 유효기간을 확인
    • ⑦ 검증이 완료되면 Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져옴
  • 세션 쿠키 방식과 가장 큰 차이점은 세션 쿠키 방식은 세션 저장소에 유저의 정보를 넣는 반면, JWT는 토큰 안에 유저의 정보를 넣는다는 점
    • 물론 클라이언트 입장에서는 HTTP 헤더에 세션 ID 또는 토큰을 실어서 보내준다는 점에서는 동일하나, 서버 측에서는 인증을 위해 암호화를 하는 점과 별도의 저장소를 이용한다는 점에서 차이가 발생
  • 장점
    • ❶ 간편함
      • 세션 쿠키 방식은 별도의 저장소의 관리가 필요하지만 JWT는 발급한 후 검증만 하면 되기 때문에 추가 저장소가 필요 없음
      • 이는 Stateless한 서버를 만드는 입장에서는 큰 강점
      • 여기서 Stateless는 어떠한 별도의 저장소도 사용하지 않는, 즉 상태를 저장하지 않는 것을 의미하므로 이는 서버를 확장하거나 유지 보수하는데 유리
    • ❷ 확장성이 뛰어남
      • 토큰 기반으로 하는 다른 인증 시스템에 접근이 가능
      • 예를 들어 Facebook 로그인, Google 로그인 등은 모두 토큰을 기반으로 인증을 하기 때문에 이를 이용하여 선택적으로 이름이나 이메일 등을 받을 수 있는 권한도 받을 수 있음
  • 단점
    • ❶ 이미 발급된 JWT에 대해서는 돌이킬 수 없음
      • 세션 쿠키 방식의 경우 만일 쿠키가 악의적으로 이용된다면 해당하는 세션을 지워버리면 됨
      • 하지만 JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능하기 때문에 악의적인 사용자는 유효기간이 지나기 전까지 신나게 정보들을 털어갈 수 있음
    • 해결책
      • 기존의 Access Token의 유효기간을 짧게 하고 Refresh Token이라는 새로운 토큰을 발급
      • 그렇게 되면 Access Token을 탈취당해도 상대적으로 피해를 줄일 수 있음
    • Payload 정보가 제한적
      • Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있음
        • 반면 세션 쿠키 방식에서는 유저의 정보가 전부 서버의 저장소에 안전하게 보관됨
      • 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없음
    • ❸ JWT의 길이
      • 세션 쿠키 방식에 비해 JWT의 길이는 길기 때문에 인증이 필요한 요청이 많아질 수록 서버의 자원 낭비가 발생하게 됨
profile
🌱 Backend-Dev | hwaya2828@gmail.com

0개의 댓글