서버 인증 유형

이병수·2020년 10월 19일
3

인증이 필요한 이유

예시

  • 사용자 A와 B가 앱을 이용한다고 했을 때 둘은 가지고 있는 컨텐츠가 기본적으로 다르다. 따라서 서버에서는 A,B가 요청을 보냈을 때 누구의 요청인 지 정확히 알아야 한다. (만일 그렇지 못하다면 자신의 정보가 타인에게 유출되는 최악의 상황 발생)

따라서 앱(프론트) 에서는 자신이 누구인지를 알만한 단서를 서버에 보내야 하며, 서버는 그 단서를 파악해 각 요청에 맞는 데이터를 뿌려주게 된다.

HTTP 통신 특성

  • HTTP 통신은 이미 응답 후 연결을 끊고 과거에 대한 정보를 담지 않는 stateless 특성을 지닌다.

    따라서 각각의 HTTP 요청에는 주체가 누구인지에 대한 정보가 필수적이다.

  • HTTP 메세지 구조는 일반적으로 헤더와 바디 두 가지로 구성되며 헤더에는 요청에 대한 정보가 바디에는 서버로 보내야 할 데이터가 들어가게된다.

보통 모바일/웹 서비스의 인증은 HTTP 헤더에 인증 수단을 넣어 요청을 보내게 된다.

인증방식

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

  • 가장 보안이 낮은 방식이다. 위에서 언급한 HTTP 요청에 인증할 수단에 비밀번호를 넣는다.

  • 데이터를 요청할 때마다 사용자의 프라이빗한 정보를 계속 보내는 건 보안에 상당히 안좋다. 해커가 마음만 먹으면 요청을 가로채서(intercept) 사용자의 계정정보를 알 수 있다.

  • 그렇기에 실제 서비스에 쓰지 않는 방식이다(HTTP 요청을 암호화해서 보안을 높이는 방식인 HTTPS가 있으나 그래도 안쓰인다)

장점

  1. 인증을 테스트 할 때 빠르게 시도해 볼 수 있다

단점

  1. 보안에 매우 취약
  2. 서버에서 신호가 올 때 마다 Id, Pw를 통해 유저가 맞는 지 인증해야 한다. 이는 매우 비효율적

계정 정보를 매 요청시 보내는 위 방식이 보안에 취약하여 다음으로 나온 방식이 Session / Cookie 방식이다.

순서를 요약하면 아래와 같다.

  1. 사용자가 로그인을 한다.
  2. 서버에서는 계정정보를 읽어 사용자를 확인한 후, 사용자의 고유한 ID값을 부여하여 세션 저장소에 저장한 후, 이와 연결되는 세션ID를 발행합니다.
    3 사용자는 서버에서 해당 세션ID를 받아 쿠키에 저장을 한 후, 인증이 필요한 요청마다 쿠키를 헤더에 실어 보냅니다.
  3. 서버에서는 쿠키를 받아 세션 저장소에서 대조를 한 후 대응되는 정보를 가져옵니다.
  4. 인증이 완료되고 서버는 사용자에 맞는 데이터를 보내줍니다.

장점

  1. 계정정보를 담아 인증하는 방식보다 보안상의 이점을 가진다
    - 세션/쿠키 방식은 기본적으로 쿠기를 매개로 인증을 거친다. 여기서 쿠키는 세션 저장소에 담긴 유저 정보를 얻기 위한 열쇠이다.

    따라서 쿠키가 담긴 HTTP 요청이 도중에 노출되더라도 쿠기 자체(세션ID)는 유의미한 값을 가지고 있지 않다.

  2. 사용자마다 고유의 ID값을 발급 받기에 서버의 자원에 접근하기 용이

    • 사용자A는 1번, B는 2번 고유의 ID 값을 받기에 서버에서는 쿠키 값을 받았을 때 일일이 회원정보를 확인할 필요없이 바로 어떤 회원인지 확인할 수 있다

단점

  1. 세션 하이재킹 가능
    - 장점 1에서 쿠키를 탈취 당하더라도 안전하다고 했는데 문제가 있다. 만일 A 사용자의 HTTP 요청을 B사용자(해커)가 가로챘다면 그 안에 쿠키도 훔칠 수 있다. 그리고 B사용자는 그 훔친 쿠키를 이용해 HTTP 요청을 보내면 서버의 세션 저장소에서는 A 사용자로 오인해 정보를 잘못준다.

    해결책 : 1) HTTPS를 사용해 요청 자체를 탈취해도 안의 정보를 읽기 힘들게 만든다.
    2) 세션에 유효시간을 넣어준다.

  2. 서버세어 세션 저장소를 사용한다고 했는데 이는 서버에 추가적인 저장공간을 필요로 하기에 자연스레 부하도 올라간다.

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

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

토큰의 구조

  • 토큰을 만들기 위해서는 크게 Header,Payload, Verify Signature가 필요

토큰
Header : 위 3가지 정보를 암호화할 방식(alg), 타입(type) 등이 들어간다.
Payload : 서버에서 보낼 데이터가 들어간다. 일반적으로 유저의 고유 ID값, 유효기간이 들어간다.
Verify Signature : Base64 방식으로 인코딩한 Header,payload 그리고 SECRET KEY를 더한 후 서명된다.

결과
Encoded Header + "." + Encoded Payload + "." + Verify Signature

Header, Payload는 인코딩될 뿐(16진수로 변경), 따로 암호화되지 않는다.
따라서 JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있다
하지만 Verify Signature는 SECRET KEY를 알지 못하면 복호화할 수 없다

A 사용자가 토큰을 조작하여 B 사용자의 데이터를 훔쳐보고 싶다고 가정하겠습니다. 그래서 payload에 있던 A의 ID를 B의 ID로 바꿔서 다시 인코딩한 후 토큰을 서버로 보냈습니다. 그러면 서버는 처음에 암호화된 Verify Signature를 검사하게 됩니다. 여기서 Payload는 B사용자의 정보가 들어가 있으나 Verify Signature는 A의 Payload를 기반으로 암호화되었기 때문에 유효하지 않는 토큰으로 간주하게 됩니다. 여기서 A사용자는 SECRET KEY를 알지 못하는 이상 토큰을 조작할 수 없다는 걸 확인할 수 있습니다.`

인증방식

  1. 사용자가 로그인을 한다.
  2. 서버에서는 계정정보를 읽어 사용자를 확인 후, 사용자의 고유한 ID값을 부여한 후, 기타 정보와 함께 Payload에 넣습니다.
  3. JWT 토큰의 유효기간을 설정합니다.
  4. 암호화할 SECRET KEY를 이용해 ACCESS TOKEN을 발급합니다.
  5. 사용자는 Access Token을 받아 저장한 후, 인증이 필요한 요청마다 토큰을 헤더에 실어 보냅니다.
  6. 서버에서는 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후, 조작 여부, 유효기간을 확인합니다.
  7. 검증이 완료된다면, Payload를 디코딩하여 사용자의 ID에 맞는 데이터를 가져옵니다.

세션/쿠카 방식과 차이

가장 큰 차이점은 세션/쿠키는 세션 저장소에 유저의 정보를 넣는 반면, JWT는 토큰 안에 유저의 정보들이 넣는다는 점입니다. 물론 클라이언트 입장에서는 HTTP 헤더에 세션ID나 토큰을 실어서 보내준다는 점에서는 동일하나, 서버 측에서는 인증을 위해 암호화를 하냐, 별도의 저장소를 이용하냐는 차이가 발생합니다

장점

  1. 별도의 저장소가 필요 없기에 간편하다.

    • 세션/쿠키 방식은 세션 저장소 관리 필요 그러나 JWT는 토큰 안에 유저의 정보들이 넣어진다. 물론 클라이언트 입장에서는 HTTP헤더에 세션 ID토큰을 실어서 보내주다는 점에서 동일하나, 서버 측에서는 인증을 위해 암호화를 하냐, 별도의 저장소를 이용하냐는 차이가 발생한다
  2. 확장성이 뛰어나다.

    • 토큰 기반으로 다른 인증 시스템에 접근 가능 예를 들어 Facebook 로그인, Google 로그인 등은 모두 토큰을 기반으로 인증을 한다. 이에 선택적으로 이름이나 이메일 등을 받을 수 있는 권한도 받을 수 있다.

단점

  1. 이미 발급된 JWT에 대해 돌이킬 수 없기에 악의적 이용시 지속 피해 발생.
    • 세션/쿠키의 경우 만일 쿠키가 악의적으로 이용된다면, 해당하는 세션을 지워버리면 된다. 하지만 JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능하다. 따라서 악의적인 사용자는 유효기간이 지나기 전까지 신나게 정보들을 털어갈 수 있다

해결책으로 기존의 Access Token의 유효기간을 짧게 하고 Refresh Token 이라는 새로운 토큰을 발급한다. 그렇게 되면 Access Token을 탈취해도 상대적 피해를 줄일 수 있다.

  1. Payload 정보가 제한적이다.

    • Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있다. (세션/쿠키 방식에서는 유저의 정보가 전부 서버의 저장소에 안전하게 보관된다) 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없다.
  2. JWT의 길이가 길다.

    • 세션/쿠키 방식에 비해 JWT의 길이는 길다. 따라서 인증이 필요한 요청이 많아질 수록 서버의 자원낭비가 발생한다.

1개의 댓글

comment-user-thumbnail
2022년 4월 5일

좋은글 감사합니다.

답글 달기