Sua Blog
JWT 어디에 저장해야할까?
2022-07-28 — etc
사용자 인증
인증과 인가
- 인증: 유저가 누구인지 확인하는 과정, 회원가입하고 로그인 하는 것.
- 인가: 유저에 대한 권한을 허락하는 것.
사용자 인증 방식
서버(세션) 기반 인증
- 기존의 인증 시스템은 서버 기반의 인증 방식으로, 서버 측에서 사용자들의 정보를 기억하고 있어야 한다.
- 사용자들의 정보를 기억하기 위해서는 세션을 유지해야 하는데, 메모리나 디스크 또는 데이터베이스 등을 통해 관리한다.
- 서버 기반의 인증 시스템은 클라이언트로부터 요청을 받으면, 클라이언트의 상태를 계속해서 유지하고 이 정보를 서비스에 이용하는데, 이러한 서버를 Sateful 서버라고 한다.

세션
- 사용자가 인증을 할 때, 서버는 인증 정보를 저장해야하고 이를 세션(session)이라고 부른다.
- 대부분의 경우 메모리에 저장하는데, 로그인 중인 사용자가 늘어날 경우에는 서버의 RAM에 부하가 걸리게 된다.
확장성
- 사용자가 늘어나게되면 더 많은 트래픽을 처리하고 여러 프로세스를 돌리기위해 서버를 확장해야한다.
- 세션을 사용하면 세션을 분산시키는 시스템을 설계해야하지만 이러한 과정은 어렵고 복잡하다.
CORS
- 세션을 관리할 때 자주 사용되는 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어있다.
- 따라서 쿠키를 여러 도메인에서 관리하는 것은 번거롭다.
이러한 문제들 때문에 토큰 기반의 인증 시스템을 사용하게 된다.
토큰 기반 인증
- 사용자에게 토큰을 발급하고, 서버에 요청할 때 헤더에 토큰을 함께 보내도록 하여 유효성 검사를 한다.
- 인증 정보를 서버나 세션에 유지하지 않고 클라이언트 측에서 들어오는 요청만으로 작업을 처리한다.
- 즉, 서버기반 인증시스템과 달리 상태를 유지하지 않으므로 Stateless한 구조를 갖는다.

무상태성 & 확장성
- 토큰은 클라이언트 측에 저장되기 때문에 서버는 완전히 Stateless하며, 서버와의 연결고리가 없기 때문에 확장하기 적합하다.
보안성
- 클라이언트가 서버로 요청을 보낼 때 쿠키를 전달하지 않으므로 쿠키 사용에 의한 취약점이 사라진다.
확장
- 토큰 기반의 인증 시스템에서는 토큰에 선택적인 권한만 부여하여 발급할 수 있으며 OAuth의 경우 facebook, google 등과 같은 소셜 계정을 이용하여 다른 웹서비스에서도 로그인을 할 수 있다.
여러 플랫폼 및 도메인
- 토큰을 사용하면 어떤 디바이스, 어떤 도메인에서도 토큰의 유효성 검사를 진행한 후에 요청을 처리할 수 있다.
최근 Json 포맷을 이용하는 JWT(Json Web Token)을 주로 사용한다.
OAuth
접근 위임을 위한 개방형 표준 프로토콜.
OAuth 동작에 관여하는 참여자는 크게 3가지이다.
- Resource Server: 자원 보유하고 있는 서버 (facebook, google 등)
- Resource Owner: 자원의 소유자(로그인하려는 유저)
- Client: Resource Server에 접속해서 정보를 가져오려고하는 클라이언트(웹 어플리케이션)
OAuth Flow
- Client 등록 Resource Server를 이용하기 위해 서비스를 등록하고 승인을 받아야한다.
- Resource Owner의 승인 Resource Owner는 Resource Server에 접속하여 로그인한다. 로그인이 완료되면 Resource Server는 Client를 검사한다.
- Resource Server의 승인 Resource Owner의 승인이 되면 redirect url로 클라이언트를 redirect 시킨다. 이 때 access token을 발급하기전에 authorization code를 함께 발급하고 resource server는 정보를 검사한 다음, 유효한 요청이면 access token을 발급한다.
- Resource Server의 자원 사용 client는 해당 토큰을 저장해두고 resource server의 자원을 사용하기 위한 api 호출시 해당 토큰을 헤더에 담아 보낸다.
JWT
JSON Web Token은 개방형 표준(open standard)으로써 전자 서명된 토큰을 사용하는 것이다. base64 encoded string 3개가 점(.)으로 나눠진 토큰이다. JSON 형태의 토큰이고 {header}.{pload}.signature 형태로 구성되어 있고 서버가 생성한다.
HEADER (ALGORITHM & TOKEN TYPE)
- type: 토큰의 타입
- alg: 토큰의 서명을 발행하는데 사용된 해시 알고리즘
PAYLOAD (DATA)
- iat: issued at. 토큰이 발생된 날짜와 시간
- exp: expiration. 토큰 만료 시간
VERIFY SIGNATURE
- 토큰의 유효성 검사에 사용
JWT 디코딩

HS256 : HMAC SHA256 의 줄임말이다. 서명을 위한 알고리즘으로 대칭키를 이용한다.
토큰의 종류와 저장
access token, refresh token
- JWT를 통한 인증 방식의 문제는 제 3자에게 탈취당할 경우 보안에 취약하다는 점이다.
- 유효기간이 짧은 token의 경우 그만큼 사용자는 로그인을 자주해서 새롭게 token을 발급받아야 하므로 불편하다.
- 그러나 유효기간을 늘리면 토큰을 탈취당했을 때 보안에 더 취약해지게된다.
- refresh token은 access token과 똑같은 형태의 JWT이다.
- 처음 로그인을 완료했을 때 access token과 동시에 발급되는 refresh token은 긴 유효기간을 가지면서 access token이 만료됐을 떄 새로 발급해주는 열쇠가 된다.
- access token은 탈취당하면 정보가 유출되는건 동일하지만 짧은 유효기간 안에만 사용이 가능하기에 더 안전하다는 의미이다.
- refresh token이 만료되면 사용자는 새로 로그인해야한다.
localStorage, http cookie
LocalStorage
[장점]
- CSRF 공격에 안전하다
- 자동으로 request에 담기는 쿠키와 달리 js 코드에 의해 헤더에 담기므로 XSS를 뚫지 않는 이상 공격자가 request를 보내기 어렵다
[단점]
- XSS 공격에 취약하다
- 공격자가 localstorage에 접근하는 js 코드 한줄이면 localStorage에 접근할 수 있다
http cookie
[장점]
- XSS 공격으로부터 localStorage에 비해 안전하다
- 쿠키의 httpOnly(서버에서 설정) 옵션을 사용하면 js에서 쿠키에 접근이 불가능하다. (하지만 js로 request를 보낼 수 있으므로 자동으로 request에 실리는 쿠키의 특성상 요청을 위조할 수 있다 XSS로부터 완전히 안전한 것은 아님)
[단점]
- CSRF 공격에 취약하다
- 자동으로 http request에 담아서 보내기 때문에 공격자가 request url만 알면 사용자가 관련 link를 클릭하도록 유도해 request를 위조할 수 있다
csrf token
- CSRF Token은 임의의 난수를 생성하고 사용자의 매 요청마다 해당 난수 값을 포함시켜서 전송시킨다.
- 이후 백엔드에서는 요청을 받을 때 마다 세션에 저장된 토큰값과 요청 파라미터에 전달된 토큰 값이 같은지 검사한다.
참고
https://mangkyu.tistory.com/55
https://tecoble.techcourse.co.kr/post/2021-07-10-understanding-oauth/
https://sdardew-valley.tistory.com/154
https://minkukjo.github.io/cs/2020/08/15/Security-1/
https://velog.io/@0307kwon/JWT는-어디에-저장해야할까-localStorage-vs-cookie