사용자 인증 프로세스에서 토큰인증방식에 대하여

0

개발지식공부

목록 보기
1/6

✏️ 고민했던 이유

▶️ 21년 종합설계프로젝트 과목을 수강하면서 '가장'이라는 공동 구매 플랫폼의 벡엔드 개발자로서 참가하였습니다. API 개발과 DB 설계의 임무를 맡았었는데, API 기능 중 사용자 인증 과정에서 보안에 대한 부분을 신경쓰지 못하였습니다. 그래서 서버와 클라이언트 간의 사용자의 민감한 정보를 주고 받는 일이 존재하였습니다.

▶️ 22년 여름방학 때 앞서 말했던 부분에 대하여 보완하고자 리액트로 간단한 로그인 페이지를 만들고, 그에 필요한 API를 따로 제작하기로 하였습니다. 그리고 로그인 과정, 사용자 인증 프로세스에서의 보안을 신경쓰는 방법을 찾아보았습니다.

▶️ 현재, 대표적인 사용자 인증 방식에는 토큰 인증 방식과 세션 인증 방식이 있습니다. 두가지 방식에는 장단점이 존재합니다. 결국에는 토큰 인증 방식으로 구현을 하였으나 다른 방식으로는 어떤 점이 좋고 나쁜지 알아보고자 합니다.
먼저 토큰 인증 방식에 대해 설명을 진행해보도록 하겠습니다.

✏️ 토큰 인증 방식이란

간단히 하면 인증에 성공한 사용자에게 토큰을 발급해주고, 사용자는 이 토큰을 이용하여 인증과정을 거친다. 사용자는 서버에 요청을 보낼 때 Header에 토큰 정보를 담아 보내고 서버는 이 토큰의 유효성 검사를 통해 사용자가 올바른 사용자인지 파악한다.

사용자의 인증 정보(ex, 로그인 여부) 같은 것을 서버에 저장할 필요가 없어서 "Stateless" 특성을 가진다. 서버 기반의 인증 방식과 달리 시스템의 확장에 용이한 장점이 있다.

장점

  1. Stateless(무상태성), Scalability(확장성)
    토큰은 클라이언트에 저장되므로 서버와의 연결에 있어서 Stateless하다. 클라이언트와 서버 간에 의존적인 관계가 없기 때문에 확장이 쉽다.
  2. 보안성
    서버에 쿠키를 전달하지 않아도 되기 때문에 쿠키 사용에 의한 보안 취약점이 사라질 수 있다.
  3. Extensibility(확장성)
    1번에서 설명한 시스템의 확장성의 의미와는 별개로 로그인 기능에서의 확장이 쉽다. 예를 들면 토큰마다 다른 권한을 부여하여 접근할 수 있는 정보나 기능을 제한할 수 있다. OAuth를 살펴보면 소셜 계정을 이용하여 여러 웹 사이트에서 회원가입이나 로그인을 가능하게 한다. OAuth에 대한 자세한 포스팅은 추후에 하도록 한다.

질문

  1. 토큰은 탈취당할 수 있다.
    쿠키에 저장되거나, Local Storage에 저장된 토큰이 탈취될 가능성은 충분히 존재한다. 그렇기 때문에 토큰 뿐만 아니라 쿠키에는 유효기간이 존재한다. 유효기간을 짧게 설정하여 토큰이 탈취되더라도 무분별하게 사용될 수 있는 일을 방지한다.
  2. 유효기간이 짧으면 사용자가 인증을 유지할 수 있는 시간도 짧나요?
    이러한 점을 보완하기 위해 토큰을 발급할 때 두 종류의 토큰을 발급한다. 첫번째는 Accuess 토큰이고, 두번째는 Refresh 토큰이다. Access 토큰은 실제로 유효성 검증에 사용되는 토큰이며 서버와의 통신에서 잦은 노출이 존재하기 때문에 짧은 유효기간을 가진다. Refresh 토큰은 Access 토큰이 만료되었을 때 Access 토큰을 재발급 받기 위해 서버에 제시하는 토큰이다. 해당 토큰만 가지고는 사용자 인증을 받을 수 없기 때문에 탈취되더라도 의미가 없다. 그러므로 긴 유효기간을 가진다.

✏️ 구현

개발에서 사용한 토큰은 JWT(Json Web Token)을 사용하였다. 기본적으로 토큰은 두가지 종류로 나뉘어 질 수 있다.

  • OAuth : 토큰은 랜덤 스트링으로 이루어져있고 이 값을 이용하여 서버에서 정보를 찾아야한다. (서버에 로직이 추가되는 것이므로 부담)
  • Claim : 토큰 자체에 필요한 정보가 담겨져 있는 경우

이러한 특성을 고려하였을 때, 서버에서 추가적인 로직을 실행할 필요가 없는 Claim 토큰을 사용하여 서버가 필요한 정보를 담아서 전달해주면 클라이언트는 해당 정보를 이용하는 형태로 구현하였습니다. 그 중 많이 사용하는 토큰이 JWT였습니다.

JWT는 헤더, 페이로드, 시그니쳐(서명) 부분으로 이루어져있습니다. 기본적으로 헤더에는 토큰타입과 암호화 알고리즘이 들어있습니다. 시그니쳐는 토큰의 무결성을 검증하기 위해 존재합니다. 비밀키가 있어야지만 복호화할 수 있습니다. 마지막으로 페이로드에는 서버가 클라이언트에게 담아서 보내줄 정보가 들어있습니다.

  1. JWT 토큰 라이브러리를 이용하여 Access 토큰과 Refresh 토큰 두가지를 발급하여 클라이언트에게 전달합니다.
  2. Access 토큰은 쿠키에 저장하고 Refresh 토큰은 Local Storage에 저장합니다.
    ❗️ (쿠키는 호환성이 높습니다. 대부분의 웹 브라우저에서 지원하고 있으나 Local Storage의 경우 지원하지 않는 웹 브라우저가 존재합니다. 이러한 경우 Access 토큰이 만료되더라도 Refresh 토큰을 이용하여 재인증 과정을 거칠 수 없습니다 -> 이러한 문제를 해결하기 위하여 두가지 모두 쿠키에 저장하는 형태로 바꿀 수 있습니다.)
  3. 쿠키에 저장된 정보를 서버에 요청을 보낼 때 header에 담아서 전송합니다.

✏️ 참고

https://mangkyu.tistory.com/55
https://velog.io/@hoo00nn/Token-%EC%9D%B8%EC%A6%9D-%EB%B0%A9%EC%8B%9D%EC%9D%B4%EB%9E%80
https://galid1.tistory.com/581

profile
최악의 환경에서 최선을 다하기

0개의 댓글