인증/인가
👓 쿠키가 왜 필요한가
인증 인가의 수단으로 쿠키 세션 토큰이 사용된다.
-
http프로토콜은 무상태와 비연결성을 가지고 있다
-
무상태와 비연결성이라는 http통신의 특징에도 불구하고, 서버가 클라이언트의 상태를 기억하는 것처럼 구현할 수 있는 수단은 쿠키이다.
🍪 쿠키
- 브라우저에 저장되는 텍스트 파일
- key-value 형태로 저장
- 별도의 삭제처리나, 요휴기간의 만료가 없는 이상 서버와의 통신에서 자동으로 주고 받는다.
- 서버에 특정 API 요청을 했을 때 서버가 응답 시 header 안에 set-cookie 속성으로 쿠키 정보를 담아주면 응답을 받은 브라우저는 쿠키를 브라우저에
자동으로 저장. (저장된 쿠키정보는 개발자도구 → 애플리케이션 → 저장용량 → 쿠키 에서 확인 가능)
- 서버에 http 요청 할 때 마다 브라우저에 저장되어 있는 쿠키는
자동으로 서버에 보내진다. (단, 동일한 Origin 또는 CORS를 허용하는 Origin에만 쿠키를 보냅니다. ex- 유튜브 서버에서 받은 쿠키는 유튜브 이용 시에만 주고 받을 수 있습니다.)

- 쿠키는 클라이언트에서 직접 추가/수정/삭제 할 수 있다.
💾 세션
- 세션이란 사용자와 서버 간의 연결이 활성화된 상태를 의미하는 개념. (또는 인증이 유지되고 있는 상태)
- 로그인 성공 → 서버에서 세션 생성 및 저장(key-value 형식) → key(sessionId)를 브라우저에 응답(by 쿠키)
쿠키-세션 인증 방식 (로그인/회원가입 시 세션 인증)
회원가입

인가(Authorization) 필요한 API 요청/응답

- 서버는 인가가 필요한 API 요청을 받으면 클라이언트 쿠키에 들어 있는 sessionId를 세션 저장소에 조회하여 있으면 DB에 데이터를 조회하여 응답
🎈 JWT(JSON Web Token)
JWT(JSON Web Token)는 클레임 기반의 토큰으로, 사용자 정보와 해당 정보의 유효성을 서명으로 포함한 토큰이며, 주로 클라이언트와 서버 간의 인증 및 정보 교환에 사용된다.
인가의 필요성
EX) Gmail에 들어갔을 때, 이메일을 열 때, 스팸을 버릴 때, 메일을 보낼 때 등등
매번 인증의 과정을 거칠 수 없기 때문에
내가 로그인이 된다는 것을 서버가 알고 있어야 한다.
내 계정으로만 활동을 시작할 때 내가 로그인이 되어있음을 알아보고 서비스를 허용
결과적으로 인증은 로그인, 인가는 인증을 받은 사용자가 서비스안에서 돌아다닐 때 서버가 로그인한 사용자를 알아보고 허용하는 것
세션의 단점
사용자가 로그인에 성공하면 서버는 세션에 대한 정보를 만들고, 이를 클라이언트측(브라우저)과 서버측(메모리)에 나누어져 저장된다.
세션 방식의 한계를 극복하기 위해서JWT같은 토큰 기반의 인증 방식이 등장했다.
- 서버가 재부팅 되면 세선 정보가 사라져서 모든 사용자가 다시 로그인 해야 한다.
- 이는 서버의 메모리에 세션정보를 저장하기 때문에, 재부팅시 메모리가 초기화되기 때문이다.
- 메모리 사용량이 증가한다.
- 서버 메모리에 세션정보를 저장하는 것은 메모리의 사용량 증가를 초래하며 많은 사용자가 동시에 로그인하면 서버에 부하를 줄 수 있으며, 서버의 메모리가 부족하면 문제가 발생할 수 있다.
- 세션 아이디가 쿠키에 저장된다면 이를 이용한 세션 하이재킹 등의 공격에 취약할 수도 있다.
- 이는 세션아이디가 브라우저에 저장되있는 것을 통한 문제로서 일어난다.
- 트래픽이 많은 웹사이트의 경우 부하가 발생할 수 있다.
- 모든 요청에 세션 아이디를 포함하여 보내줘야 하기 때문에 일어난다.
- 서버가 다운이 되면 세션 정보를 잃을 수 있다.
JWT 토큰 방식
JWT(JSON Web Token)는 서버 측에서 사용자의 상태를 유지하지 않고, 토큰 자체에 사용자 정보를 포함하여 클라이언트에게 전달된다. 이는 세션과의 주요 차이점 중 하나이다.
- 여러 세션 기반의 인증 방식에서는 서버가 사용자의 상태를 기억하고 유지하기 위해 세션을 생성하고 관리한다. 이에 반해 JWT는 토큰을 발급하여 클라이언트에 전달하고, 서버는 이 토큰을 사용하여 사용자를 인증한다. 서버는 토큰을 클라이언트에게 전달한 후, 그 토큰을 통해 클라이언트가 자신을 인증하고 자신의 상태를 서버에 전달한다.
JWT 토큰의 구성
암호화

해석

1. 헤더를 디코더 하면 두가지 정보가 담겨 있다.
- type: 토큰의타입이 들어가며 항상 JWT가 들어간다.(고정값)
- alg(알고리즘의 약자): 여기에는 서명값(3)을 만드는데 사용될
알고리즘(HS256등 여러 암호화 방식 중 하나를 지정할 수 있다.)이 지정된다.
2. 페이로드에는 클레임(claim)이 포함되어 있다.
-
서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용, 이를테면 사용자의 닉네임이나 서비스상의 레벨, 관리자의 여부등을 서비스 측에서 원하는대로 담을 수 있다.
-
이렇게 토큰에 담긴 사용자 정보 등의 데이터를 Claim이라고 한다.
-
이후 요청마다, 이제는 서버가 아닌 사용자로부터 서버로 보내지고, 이렇게 토큰 자체에 이런 정보들이 들어있으면 서버가 요청마다 일일이 데이터베이스에서 뒤져봐야 할 것들이 줄어든다.
**3. 서명은 헤더와 페이로드를 합친후, 비밀키로 사용해 생성한다.
(비밀 키는 서버 측에서 안전하게 보관되어야 한다.)
- 이 서명을 통해 토큰이 변경되지 않았고, 발신자가 누구인지 확인할 수 있다.
서버는 요청에 토큰 값이 실려들어오면, 헤더, 페이로드 값을 "서버의 비밀 키" 와 함께 돌려봐서 계산된 결과값이 서명 값과 일치하는 결과가 나오는지 확인한다.
이렇게 서명값과 계산값이 일치하고, 유효기간도 지나지 않았다면 그 사용자는 로그인 된 회원으로서 인가를 받는 것이다.
이제 서버는 사용자의 상태들을 어디다가 따로 저장해둘 필요없이 이 비밀값만 가지고있으면 요청이 들어올 때마다 토큰을 스캔해서 사용자들을 걸러낼 수 있다.
JWT의 단점
Access Token과 Refresh Token을 사용하지 않는 방식으로는 일반적으로 Stateless 방식을 의미한다. JWT 자체는 기본적으로 Stateless한 특성을 가지고 있다.
- Access Token과 Refresh Token을 사용하지 않는 방식은 여러 단점이 있다.
- 실시간 세션 관리의 어려움
- JWT는 서버에서 토큰을 발급한 후에는 클라이언트에서만 상태를 유지하므로, 실시간으로 세션을 제어하기 어렵습니다
- 예를 들어 세션방식에서는 한 기기에서 로그인한 사용자가 다른 기기에서 로그인하면 이전 기기에서 자동으로 로그아웃되도록 서버에서 조치할 수 있지만, JWT는 이러한 구현이 어렵다.
- 여러 기기에서의 로그인 관리의 어려움
- JWT는 클라이언트에 상태를 저장하지 않기 때문에, 한 사용자가 여러 기기에서 로그인하는 경우에 서버에서 쉽게 관리할 수 없다.
- 예를 들어, 한 기기에서 로그인한 사용자가 다른 기기에서 로그인하면 이전 기기에서 로그아웃되도록 하는 등의 관리가 어렵다.
- 로그아웃의 어려움
이러한 단점은 특히 실시간 세션 관리와 다중 기기에서의 로그인 상황에서 발생하며, 실제 프로젝트에서는 이러한 요구사항에 따라 Access Token, Refresh Token, 세션 스토리지 등을 적절히 조합하여 사용해야 한다
Access Token과 함께 Refresh Token 발급
1. 토큰 발급
- 사용자가 로그인하면 서버에서는 Access Token과 함께 Refresh Token을 발급한다.
- Access Token은 짧은 유효 기간을 가지며, 사용자의 신원을 확인하는 역할을 한다.
- Refresh Token은 Access Token 갱신을 위한 역할을 하며, 더 긴 유효 기간을 가지고 있다.
2. 토큰 전달
- 발급된 Access Token과 Refresh Token을 안전한 방법으로 클라이언트에게 전달한다.
3. 토큰 저장
- 클라이언트는 받은 토큰을 안전한 위치에 저장한다. 일반적으로는 안전한 쿠키, 로컬 스토리지, 또는 메모리에 저장된다.
4. 토큰 갱신
- Access Token이 만료되기 전에 클라이언트는 Refresh Token을 사용하여 서버에 새로운 Access Token을 요청한다.
- 서버는 클라이언트가 보낸 Refresh Token을 검증하고, 유효하다면 새로운 Access Token을 발급한다.
각각의 역햘
ACCESS 토큰 (인증용)
ACCESS 토큰은 사용자의 인증을 확인하고, 서버에 특정 리소스에 접근할 권한이 있는지를 확인하는 데 사용된다.
- 짧은 유효 기간을 가지며, 주로 클라이언트에서 서버로 API 요청 시 헤더에 실려서 전달되어 된다.
REFRESH 토큰 (ACCESS 발급용)
REFRESH 토큰은 ACCESS 토큰이 만료되었을 때, 새로운 ACCESS 토큰을 발급받기 위한 용도로 사용된다.
- 보통 ACCESS 토큰보다 더 긴 유효 기간을 가지며, 클라이언트는 REFRESH 토큰을 사용하여 서버에 새로운 ACCESS 토큰을 요청한다.
ACCESS 토큰은 주로 실제 리소스에 접근하기 위한 권한을 확인하는 데 사용되고, REFRESH 토큰은 ACCESS 토큰이 만료되었을 때 새로운 ACCESS 토큰을 발급받기 위한 용도로 사용되었다. 이 두 토큰을 조합하여 보안성을 유지하면서도 사용자 경험을 향상시킬 수 있다.