[Web] 세션/쿠키 인증과 토큰 인증(Access Token, Refresh Token)

seomoon·2021년 7월 30일
2
post-custom-banner

인증

인증이란 / 인증이 필요한 이유

인증이란

  • 프론트엔드 관점에서 봤을 때 : 사용자의 로그인, 회원가입과 같이 사용자 입장에서 서비스의 도입 부분을 가리킴.
  • 서버사이드에서 봤을 때 : 모든 API 요청에 대해 사용자를 확인하는 작업.

인증이 필요한 이유

  • 서버에서는 요청을 받았을 때, 누구의 요청인지를 정확히 알아야 한다. 그렇지 않으면 자신의 정보가 타인에게 유출될 수 있다. 따라서 프론트엔드(앱)에서는 누가 요청하고 있는지에 대한 단서를 서버에 보내야 하며, 서버에서는 그 단서를 정확히 파악해 맞는 데이터를 뿌려줘야 한다.

HTTP 요청에 대해

  • 모바일, 웹 서비스에서 가장 많이 쓰이는 통신 방식.
  • 응답 후 연결이 끊기며(비연결성), 서버가 클라이언트가 누구인지 기억하지 못한다(무상태). 즉 지금 보낼 HTTP 요청은 이전에 보냈던 HTTP 요청과는 전혀 관계가 없다. 따라서 각각의 HTTP 요청에는 주체가 누구인지에 대한 정보가 필수적이다. (인증이 필요 없다면 필요없을 수도 있지만, 대부분의 경우 인증이 필수적)
  • 서버에 요청을 보내는 작업 = HTTP 메세지를 보내는 것.
  • HTTP 메세지 : 헤더, 바디 두 가지로 구성됨. 한 줄의 공백이 헤더와 바디를 구분짓는 역할을 함. 헤더에는 요청에 관한 기본적인 정보들이 들어가고, 바디에는 서버로 보내야 할 데이터가 담긴다. 보통 모바일/웹 서비스의 인증은, HTTP 메세지의 헤더에 인증 수단을 넣어 요청을 보냄으로써 이루어진다.

인증 방식

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

  • HTTP 요청 메세지 헤더의 인증 수단에 비밀번호를 넣는 방식이다.
  • 보통 앱에서 서버로 HTTP 요청을 할 때는, 따로 암호화를 하지 않는다.따라서 데이터를 요청할 때마다 사용자의 프라이빗한 정보를 계속해서 보내게 되고, 이러한 HTTP 요청을 가로채면 사용자의 계정정보를 쉽게 알 수 있다.
  • HTTP 요청을 암호화해서 보안을 높이는 방식의 HTTPS가 있지만, HTTPS로도 이러한 방식은 잘 쓰이지 않는다.
  • 보안에 매우 취약하며, 서버에서 신호가 올 때마다 ID, PW를 통해 유저가 맞는지 인증해야하므로 비효율적이기도 하다. 최악의 인증방식이라고 볼 수 있다. 실제 서비스에서는 쓰지이 않고, 개발 단계에서 인증 절차를 빠르게 테스트해볼 때 사용해볼 수는 있다.

2. 세션/쿠키 방식

  • 첫 번째 방식의 단점을 보완하기 위해 나온 것이 세션/쿠키 방식의 인증이다.
  • 과정 : 사용자 로그인 -> 서버에서 사용자 확인 후 세션 ID 발행 -> 사용자는 서버에서 받은 세션 ID를 쿠키에 저장 하고, 데이터를 요청할 때마다 쿠키를 헤더에 실어 보낸다 -> 서버는 쿠키를 받아 세션저장소에서 대조한 뒤(인증완료) -> 사용자에 맞는 데이터를 보내준다.
  • 세션 : 서버에서 가지고 있는 정보 / 쿠키 : 사용자에게 발급된 세션 ID (세션을 열기 위한 열쇠)
  • 쿠키만으로 인증을 하는 경우 -> 서버의 자원은 사용하지 않고 클라이언트가 인증 정보를 책임지게 됨.이 경우 첫 번째 방식처럼 HTTP 요청을 탈취당하면 정보를 다 털리게 됨. 보안과는 상관없는 단순한 장바구니나 자동로그인 설정 같은 경우에는 유용하게 쓰인다.
  • 세션을 사용해 인증을 하는 경우 -> 사용자는 쿠키를 이용하고, 서버에서는 쿠키를 받아 세션의 정보에 접근하는 방식으로 인증을 한다. 인증의 책임을 서버가 지기 때문에 보안성이 높아짐(사용자가 해킹당하는 것보다 서버가 해킹당하는 것이 훨씬 어렵기 때문).
  • 장점 :
    • HTTP 요청에 사용자 정보를 직접 담는 대신 쿠키를 담는다. 쿠키(세션 ID) 자체는 유의미한 값을 가지고 있지 않기 때문에, HTTP 요청이 도중에 노출되더라도 첫 번째 방식보다 상대적으로 안전하다.
    • 서버에서 쿠키 값을 받으면, 회원정보를 일일히 대조해볼 필요 없이 바로 어떤 회원인지 알 수 있어서 서버의 자원에 보다 효율적으로 접근할 수 있다.
  • 단점 :
    • 사용자 A의 쿠키가 들어있는 HTTP 요청을 해커가 가로챘다면, 훔친 쿠키를 이용해 HTTP 요청을 보낼 수 있다. 그러면 서버의 세션 저장소에서는 사용자 A로 오인해 정보를 잘못 뿌려주게 된다. (세션 하이재킹 공격)=> 해결책: HTTPS를 사용해 요청을 탈취해도 안의 정보를 읽기 힘들게 하거나, 세션에 유효시간을 설정해준다.
    • 서버에서 세션 저장소를 사용하기 위해 추가적인 저장공간을 필요로 하게 되고, 자연스럽게 부하도 높아지게 된다.

3. 토큰 기반 인증 방식 (JWT, JSON Web Token) : Access Token을 사용하는 인증 방식

  • 인증에 필요한 정보들을 암호화시킨 토큰을 사용해 인증하는 방식.

  • 사용자가 Access Token을 HTTP 헤더에 실어 서버로 보낸다.

  • 토큰의 구성 요소 :

    • Header : 토큰의 암호화 방식, 타입 등
    • Payload : 서버에서 보낼 데이터. 유저의 고유 ID 값, 유효기간 등
    • Verify Signature : 인코딩한 Header + Payload + SECRET KEY + 서명
  • 최종적인 토큰의 모습 : Encoded Header + “.” + Encoded Payload + “.” + Verify Signature

  • Header, Payload는 인코딩되어 16진수로 변경되지만, 따로 암호화되지는 않는다. 따라서 Header, Payload는 디코딩만으로 누구나 쉽게 확인할 수 있다.

  • Verify Signature는 SECRET KEY를 알지 못하면 복호화할 수 없다.

  • 인증 과정 :

    https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995EC2345B53368912

    • 사용자 로그인
    • 서버에서 사용자 확인 -> 사용자에게 고유한 ID 값 부여 -> 기타 정보와 함께 Payload에 담음 -> 토큰의 유효기간 설정
    • SECRET KEY를 이용해 Access Token 발급 -> Access Token과 함께 사용자에게 응답
    • 사용자는 Access Token을 받아 저장 -> 데이터 요청 시 토큰을 헤더에 실어 보냄
    • 서버에서 해당 토큰의 Verify Signature를 SECRET KEY로 복호화한 후 조작 여부, 유효기간 확인
    • 검증이 완료되면 Payload를 디코딩하여 사용자의 ID에 맞는 데이터 가져와 응답
  • 세션/쿠키 인증 방식과의 차이점 :

    • 세션/쿠키는 세션 저장소에 유저 정보를 넣기 때문에, 서버 측에 별도의 세션 저장소가 필요함.
    • 토큰 인증 방식은 토큰 안에 유저의 정보들을 넣기 때문에 별도의 저장소는 필요하지 않음. (별도의 저장소가 필요하지 않은 대신, 암호화가 필요함. )
  • 장점 :

    • 추가 저장소가 필요하지 않아 간편하다. Stateless(어떠한 별도의 저장소도 사용하지 않는, 즉 상태를 저장하지 않는)한 서버를 만드는 데 큰 강점. 서버를 확장하거나 유지, 보수하는 데 유리함.
    • 확장성이 뛰어나다. 토큰 기반으로 하는 다른 인증 시스템(Facebook 로그인, Google 로그인 등)에 접근이 가능하다.
  • 단점 :

    • 악의적으로 이용되는 경우 해당하는 세션을 지워버리면 되는 세션/쿠키 인증방식과는 달리, 한 번 발급되면 유효기간이 완료될 때까지는 계속 사용이 가능하다. -> Refresh Token을 통해 어느 정도 해결할 수 있다.
    • Payload 정보가 제한적이다. Payload는 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있다. 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없다. (세션/쿠키 방식에서는 유저의 정보가 전부 서버의 저장소에 안전하게 저장된다. )
    • 세션/쿠키 방식에 비해 길이가 길다. 따라서 인증이 필요한 요청이 많아질수록 서버의 자원낭비가 발생하게 된다.

4. Refresh Token

  • Access Token (JWT)를 이용한 인증 방식의 문제점 : 제3자에게 토큰을 탈취당할 경우 보안에 취약할 수 있다. 이 점을 해결하기 위해 유효기간을 짧게 하면, 그만큼 사용자가 로그인을 자주 해야 하는 불편함이 생긴다.

  • Access Token의 유효기간을 짧게 하면서도, 사용자의 불편함을 줄일 수 있는 방법으로 나온 것이 Refresh Token이다.

  • Refresh Token은 Access Token과 똑같은 형태의 JWT이다. Refresh Token은, 처음에 로그인을 완료했을 때 Access Token과 동시에 발급된다. Refresh Token은 긴 유효기간을 가지면서, Access Token이 만료되었을 때 Access Token을 새로 발급해주는 열쇠로 사용된다.

  • Refresh Token의 유효기간이 만료되었을 경우에만 사용자가 새로 로그인을 하면 된다. 단, Refresh Token도 탈취될 가능성이 있기 때문에 적절한 유효기간 설정이 필요하다. (주로 2주 정도)

Refresh Token + Access Token을 활용한 인증 과정

  • 사용자 로그인 -> 서버에서 사용자 확인(회원 DB에서 ID, PW 값 비교) -> 로그인 완료

  • 서버에서 Access Token, Refresh Token 발급, 응답에 담아 보냄 (이 때 일반적으로 회원DB에 Refresh Token을 저장해 둠)

  • 사용자는 Refresh Token을 안전한 저장소에 저장한 후, Access Token만 헤더에 실어 요청을 보냄.

  • 서버에서 Access Token을 검증한 후 응답함.

  • Access Token이 만료된 경우, 사용자는 Refresh Token과 Access Token을 같이 서버로 보냄.

  • 서버는 받은 Access Token과 (조작 여부 확인) Refresh Token (회원 DB에 저장해둔 Refresh Token과 대조)을 확인한 후, 새로운 Access Token을 발급해 준다.

  • 사용자는 새로 발급받은 Access Token을 헤더에 실어 다시 API 요청을 진행한다.

  • 장점 : Access Token만 사용할 때보다 안전하다.

  • 단점 : 검증 프로세스가 길어 구현이 복잡해졌다. Access Token이 만료될 때마다 재발급하는 과정에서 생기는 HTTP 요청횟수가 많아 서버의 자원 낭비가 발생한다.

profile
💛💛 🖥🏐🛋🥗💵📖 💛💛
post-custom-banner

0개의 댓글