본문 바로가기
web/Vue

JWT에 대한 고찰

by 뽀리님 2023. 9. 13.

로그인시 JWT 를 어디다 보관해야할지, 어떻게 보관해야 안전할 지 골똘히 생각하다가 정리하는 포스팅..

 

일단 JWT 를 왜쓰는걸까?

남들이 다 써서^^? 걍 기존 시스템이 jwt라? 위에서 시켜서??

물론 남들이 많이 쓰는덴 다 이유가 있다.

 

JWT 는 stateless 해서 쓴다.  사용자 정보를 DB에 저장해놓고 요청할때 마다 I/O 해서 검증하는건 stateful 한 방식인 세션방식이다.

On-premise(온-프레미스) Cloud(클라우드) 시스템으로 넘어가면서 수평적확장(Horizontal Scale Out) 방식을 쓴다.

즉, 사용자가 1000명이었을 땐 서버가 1개였다가 갑자기 급증해서 10000명이 되면 클라우드 플랫폼이 이를 감지하여 서버를 10개 늘리는걸 수평적 확장이라 한다.

이게 stateless 방식을 쓰는 이유중 하나이다.

 

만약에 Server_1 에서 stateful 인 세션방식을 쓰고 있다고 가정해보자.

그럼 유저1 ~ 유저100 까지의 정보가 Server_1 에서 관리된다.

근데 트래픽이 갑자기 10000명으로 늘어서 서버가 10개로 증가하게 되면?????

Server_2 ~ Server_10 까지는 유저1 ~ 유저100의 정보를 가지고 있지 않다. 

그렇다고 유저1~100 까지 Server_1 에 로그인했다면 100명의 정보를 일일이 Server_2 ~ Server_10 까지 동기화 시켜야 하는데, 사실상 어렵고 번거롭다.

 

그래서 Stateless 방식인 JWT 를 쓰는 것이다.

User ID(사용자정보) + Private Key 를 해싱한 값인 JWT 를 유저에게 보내고,

유저가 Server_1 이든 Server_6 이든 HTTP Request 를 JWT 로 보내면

서버에서는 간편하게 JWT를 다시 복호화하여 equals() 로 비교만 하면된다.

따라서 수평적 확장에 잘 받는 요즘 클라우드 환경에서  유용한 방식인 것이다.

 

그럼 이 JWT 는 어디다 보관해야 안전할까?...

 

사실 LocalStorage, SesstionStorage, IndexDB 엄청 많았지만

나는 Nuxt (SSR) 로 진행하고 있었기에 해당사항은 없었다.

그리고 로컬스토리지나 세션스토리지도 자바스크립트로 까면 볼 수 있기 땜시롱 XSS (Cross Site Script) 공격에 취약하다.

(XSS : 스크립트를 통해 html이나 js 동작시켜 사용자의 인증 정보를 탈취)

 

특히나 자동로그인 기능 따위를 집어넣게 되는 순간 이 문제는 더욱 골치 아파진다.

(리프레시토큰을 어디다 저장해야하는가...?)

 

일단 내가 생각한방법은,

1. 로그인시 AccessToken 과 RefrshToken을 발급한다.
AcessToken  -> 만료기간이 있는 Cookie나 local_variable 로 생성
RefreshToken  -> HttpOnly Secure Cookie

2. 로그인시 통신은 SSL(Https) 로 통신한다.

3. RefreshToken 은 DB에 저장하여 관리한다.(추후 탈취되어도 유효성 체크를 위함)

4. Access-Control-Allow-Origin 설정을 하여 특정 도메인에서 오는 요청만 허용

 

HttpOnly 옵션을 쓰게되면 일단 스크립트로 접근할 수가 없으므로, XSS 공격엔 안전하다.

Set-Cookie: 쿠키명=쿠키값; path=/; HttpOnly

 

HttpOnly라는 접미사만 추가함으로써 HTTP Only Cookie가 활성화 되며, 위에서 말한 XSS와 같은 공격이 차단된다. HTTP Only Cookie를 설정하면 브라우저에서 해당 쿠키로 접근할 수 없게 되지만, 쿠키에 포함된 정보의 대부분이 브라우저에서 접근할 필요가 없기 때문에 HTTP Only Cookie는 기본적으로 적용하는 것이 좋다.

HttpOnly 속성은 클라이언트(브라우저 ) 에서 설정할 없는 옵션이며, 서버단에서 설정할 있는 옵션이다.

 

https://ssmyefrin.tistory.com/26

 

HttpOnly + Secure Cookies 생성

Https 로 설정까지 마쳤다면 HttpOnly 쿠키를 설정해보자 로그인 시 Refresh 토큰발급을 HttpOnly 쿠키로 발급하고자한다. httpOnly란 Set-Cookie HTTP reponse 헤더에 포함되는 flag이다. cookie를 생성할 때 HttpOnly

ssmyefrin.tistory.com

 

 

하지만 쿠키는 CSRF (Cross Site Request Forgery) 공격엔 취약하다.

(CSRF : 인증된 유저가 의도하지 않게 서버에 공격을 하게 만듬)

 

이를 막기위해서 HTTPS 때에만 쿠키를 전송하도록 Secure 옵션을 적용한다.

Set-Cookie: 쿠키명=쿠키값; path=/; secure

또한 쿠키에 담긴 토큰 단독으로 DB 수정/삭제가 되지 않도록 하기위해 나는 토큰마다 권한을 적용시켜 제한을 두었다.

 

RefreshToken DB 저장

RefreshToken을 탈취당할 경우도 생각한다면 Client가 전달한 RefreshToken의 값과 DB or Redis 휘발성 저장소가 아닌 곳에서 비교하여 맞는지 확인한다면 앞에서 말했 듯 탈취를 당해도 막아낼 수 있다.

아니면 Client 는 인덱스 정보만 저장해놓고 요청시 인덱스를 가지고 DB 데이터와 비교한뒤 토큰을 재발급해도 된다.

 

쿠키는 브라우저에서 공용으로 사용되기 때문에 악성 사이트에서 접근가능하다. 이 경우 쿠키에 담긴 refreshToken으로 서버에 악성 요청을 보낼수 있는데 이걸 막기위해 CORS 설정을 한다.

 

CORS 에 대한 개념은 아래 위키에 설명되어있다.

https://ko.wikipedia.org/wiki/%EA%B5%90%EC%B0%A8_%EC%B6%9C%EC%B2%98_%EB%A6%AC%EC%86%8C%EC%8A%A4_%EA%B3%B5%EC%9C%A0

 

교차 출처 리소스 공유 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. -->

ko.wikipedia.org

 

 

Spring Boot 로 CORS 설정

CORS 설정은 각 부분 별로 할지, 글로벌하게 할지에 따라 세팅방법이 달라진다.

나는 인증시에만 체크할 예정이므로 전자로 진행하겠다

@CrossOrigin(origins = {...})

@CrossOrigin 어노테이션을 통해 CORS 를 설정할 수있다.

 

 

 

 

결론 :

중요정보를  담고있는 API는 HTTPS 로 보내는게 좋으며,

accessToken 은 유효기간이있는 쿠키나 로컬변수에 저장하고, accessToken 을 재발급받을 수 있는 refreshToken 은 HttpOnly Secure 옵션 쿠키로 발급해서 관리한다.

 

 

-끝-

 

 

참조 : 

 

https://blog.wishket.com/http-vs-https-%EC%B0%A8%EC%9D%B4-%EC%95%8C%EB%A9%B4-%EC%82%AC%EC%9D%B4%ED%8A%B8%EC%9D%98-%EB%A0%88%EB%B2%A8%EC%9D%B4-%EB%B3%B4%EC%9D%B8%EB%8B%A4/

https://dncjf64.tistory.com/292

https://goyunji.tistory.com/108

https://sleeg.tistory.com/entry/Spring-JWT-Refresh-Token-%EC%96%B4%EB%94%94%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C

https://velog.io/@jhy979/AccessToken-%EC%A0%80%EC%9E%A5-%EC%9C%84%EC%B9%98%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0-JWT-%EC%95%88%EC%A0%84%ED%95%9C%EA%B0%80%EC%9A%94

'web > Vue' 카테고리의 다른 글

SPA 와 SSR vs CSR  (1) 2024.02.13
Nuxt(Vue) 로 admin page 만들기 (2)  (0) 2023.09.05
Nuxt(Vue) 로 admin page 만들기 (1)  (0) 2023.09.04
Nuxt 구조  (0) 2023.09.01
Nuxt 로 Vue 환경세팅  (0) 2023.08.31