오늘이 아시안컵 16강이 있던 날인데,
축구를 보니 볼 차고 싶은 생각이 너무 들던 하루,,,
(사진은 축구하고 있는 나)
오늘은 프론트엔드를 개발하면서 로그인 세션을 어떻게 관리하였는지 작성해보겠다.
서버에서는 사용자가 로그인 되어 있는지 알 필요가 있다. 이를 위해 JWT 라는 것을 사용한다.
JWT 란 무엇이고 왜 필요할까?
1. JWT란?
JWT (JSON Web Token)는 Json 형식을 이용하여 사용자의 속성을 저장하는 Token이다.
즉, 정보를 비밀리에 전달하거나 사용자 인증 시 사용된다.
ex)
- 앱을 실행했을 때 사용자가 가진 JWT를 비교하여 자동로그인을 기능을 제공
- 상품 구매, 예약 신청 등을 시도할 때 사용자 인증
2. JWT가 필요한 이유
1) 무상태성 (Statelessness)
JWT가 필요한 첫 번째 이유는 무상태성 (statelessness)이다.
우선 무상태성이 무엇인지 짚고 넘어갈 필요가 있다.
웹 서버가 사용자의 상태를 계속해서 기억하지 않는 것을 "무상태성"이라고 한다.
예를 들어, 웹사이트에 접속할 때마다 사용자가 로그인을 해야 하면 그 웹사이트는 무상태적이다. 반대로 사용자가 한 번 로그인하면 그 상태를 계속 기억하고 있는 웹사이트는 "유상태적"이라고 할 수 있다.
현대의 웹 애플리케이션은 확장성 (시스템, 네트워크, 프로세스 등이 부하가 증가할 때 그것을 효과적으로 처리할 수 있는 능력) 을 유지하기 위해 상태를 유지하지 않는다는 원칙을 따르는 경우가 많다.
JWT는 이런 무상태적 환경에서도 사용자의 인증 정보나 권한 등을 안전하게 전달하고 관리하는 방법을 제공한다.
- JWT는 사용자 ID, 권한 등 필요한 정보를 포함하므로, 사용자가 요청을 할 때마다 데이터베이스에 접근하여 인증 정보를 확인할 필요가 없다.
- 사용자가 로그인하면 JWT가 반환되고, 이후 요청에는 이 토큰을 사용하여 서버에서 빠르게 인증할 수 있다. 이로 인해 서버는 무상태성을 유지하면서 효율적으로 인증 처리를 할 수 있다.
2) 웹 모바일 모두 활용 가능
JWT는 HTTP 헤더에 쉽게 포함될 수 있으므로, 모바일 애플리케이션에서도 쉽게 사용할 수 있다.
3) 보안
어쩌면 JWT를 사용하는 가장 중요한 사항이다.
JWT는 *디지털 서명을 통해 *데이터의 무결성을 보장한다. 서명은 비밀키를 통해 생성되기 때문에, 서명을 검증하는 측이 해당 키를 알고 있지 않는 한 토큰을 위변조할 수 없다.
*디지털 서명 : 네트워크에서 송신자의 신원을 증명하는 방법
*데이터의 무결성 : 데이터의 정확성, 일관성, 유효성이 유지되는 것
4) 필요한 모든 데이터를 포함
무상태성 (Statelessness) 에서도 언급했지만, JWT는 필요한 모든 정보를 자체적으로 가지고 있다.
이러한 점 덕분에, 중앙의 인증 서버나 데이터베이스에 의존하지 않고도 사용자의 상태와 권한을 검증할 수 있다.
3. JWT 구조 (생김새)
JWT는 보통은 “ey”로 시작하며, 3개의 부분으로 나누어져 있고 각 부분은 점(.)으로 구분되어 있다.
- Header: 토큰 유형과 토큰을 검증하는데 필요한 서명 알고리즘으로 구성되어 있다.
- Payload: 토큰에 저장할 데이터들로 구성되어 있다. 위의 예시는 id와 name, 그리고 권한을 확인하기 위한 auth로 구성했다.
- Signature: 가장 중요한 부분으로 헤더와 정보를 합친 후 발급해준 서버가 지정한 secret key로 암호화 시켜 토큰을 변조하기 어렵게 만들어준다.
4. JWT는 어떻게 활용될까? (Access Token, Refresh Token)
JWT는 서버 측 *리소스에 접근할 때 클라이언트 본인을 인증할 수 있도록 액세스 토큰(Access Token)을 발급한다.
"리소스에 접근한다"는 말은 “웹사이트나 앱의 특정 기능이나 정보를 사용하려고 할 때”라고 볼 수 있다.
다시 말해, 특정 정보나 기능을 사용하려고 시도하는 것을 의미한다.
하지만, JWT는 무상태성(Statelessness)의 방식이기 때문에 서버 측에서는 이 토큰을 갖고 있는 클라이언트가 정말 클라이언트 본인이 맞는지 확인할 수 없다는 문제점이 있다. 만약 Access Token을 다른 사람에게 탈취 당한다면 누가 본인인지 전혀 알 수가 없을 것이다.
그래서 이에 대한 보안 대책으로 리프레쉬 토큰(Refresh Token)이라는 추가적인 토큰이 제공된다. 이 토큰은 사용자 인증이 아닌 새로운 Access Token을 생성하는 용도로만 활용된다.
구체적인 리프레쉬 토큰(Refresh Token)의 구체적인 내용은 좀 더 뒤에 다뤄보자.
1) Access Token과 Refresh Token의 발급과 사용
Access Token과 Refresh Token을 간단하게 말하자면 다음과 같이 설명할 수 있다.
- Access Token: 사용자의 인증 및 권한을 확인하기 위한 토큰으로, 짧은 유효 기간을 가진다.
- Refresh Token: Access Token이 만료되었을 때 새로운 Access Token을 발급 받기 위한 토큰. 일반적으로 긴 유효 기간을 가진다.
그러면, Access Token과 Refresh Token이 어떤 과정에서 얻을 수 있고, 사용될까?
- Token 발급 (로그인 과정)
- 사용자가 ID와 비밀번호를 통해 로그인을 시도한다.
- 서버(백엔드)에서는 로그인 정보를 검증하고, 성공적인 경우 Access Token과 Refresh Token을 생성한다.
- 생성된 두 토큰을 사용자에게 전달된다.
- 이 때, 프론트엔드가 설정한 방식에 따라 사용자는 두 가지의 토큰을 보관하게 된다.
- Token 사용 1 (리소스 접근)
- 사용자는 리소스에 접근할 때 Access Token을 헤더에 포함 시켜 서버에 전송한다.
- 서버는 Access Token의 유효성을 검증하고, 유효한 경우 해당 리소스에 대한 접근을 허용한다.
- 상품 구매, 예약 신청 등을 시도할 때 서버에 Access Token을 넘겨줌으로써 유효성 검증을 하고 원하는 리소스에 접근할 수 있다.
- Token 사용 2 (자동로그인)
- 첫 로그인 시 : 사용자는 Access Token을 발급 받고, 클라이언트(웹사이트 앱)는 받은 Token을 안전하게 저장합니다.
- 재접속 시 : 사용자가 애플리케이션을 다시 방문하거나 앱을 다시 실행할 때, 클라이언트는 저장했던 Access Token을 가져와 서버에 전송한다.
- 서버는 받은 Access Token의 유효성을 검증한다. 토큰이 유효하면 사용자는 자동로그인 상태가 되며, 로그인 과정 없이 서비스를 이용할 수 있다.
2) Token의 재발급
앞선 내용에서 Access Token은 짧고, Refresh Token은 긴 유효 기간을 가진다고 하였다.
Access Token의 유효 기간이 짧은 이유는 Token을 탈취 당했을 때를 대비하기 위함이다. 공격자는 유출된 Token을 탈취하더라도 유효 기간이 지나면 사용할 수 없다. Token을 주기적으로 재발급 받도록 하여 Token이 유출되더라도 그 피해를 최소화한다는 방식인 것이다.
하지만 그렇다면 정상적인 클라이언트도 짧은 주기마다 다시 로그인해서 Access Token을 발급받아야 한다는 단점이 있다. 그래서 여기서 유효 기간이 긴 Refresh Token을 사용하는데, 정상적인 사용자는 Access Token이 만료됐다면 서버측에 Refresh Token을 전송하여 다시 로그인할 필요 없이 Access Token을 발급받을 수 있다. 당연히 이 Refresh Token이 없는 공격자는 다시 토큰을 발급받을 수 없기 때문에 보안 측면에서 좀 더 안전하다고 할 수 있다.
여기까지는 JWT에 대해 알아보았다.
다음 글에서는 글 작성자의 프로젝트 (프론트엔드 개발 파트)에서 JWT를 어떻게 관리하고 있는지 정리될 예정이니 참고하면 좋을 것 같다.
'JWT' 카테고리의 다른 글
[JWT] 로그인 세션 관리하기3 (토큰이 만료된다면? - Axios 인터셉터) (0) | 2024.02.02 |
---|---|
[JWT] 로그인 세션 관리하기 2 (Session Storage, Local Storage, Recoil) (0) | 2024.02.01 |