Storing JWTs

rang-dev·2020년 3월 18일
0

Recap - Local Storage

Storing Tokens in Web Browsers Using Local Storage


서버에 전송되는 모든 subsequent requests에 어떻게 JWT를 포함시킬까? 우리는 user가 매 subsequent request마다 그들의 credentials와 interact해야 하는 것을 원치 않는다. 대신 우리는 front-end가 우리를 위해 이 작업들을 처리해주길 바란다.

그렇기 위해서는 JWT를 client안에 locally하게 저장해야한다. succeeful login-in 후에 (1)JWT를 저장하고, reqeust를 server에 전송해야할 때 JWT를 저장했던 곳에서 (2)JWT를 가져온다. 두 작업은 모두 client 내에서 발생한다. 우리의 client는 Google Chrome이나 Firefox와 같은 web browser에서 돌아가는 website로 한정한다. 그렇다면 우리는 token을 local storage에 저장할 수 있다.

Local stroage는 JavaScript의 interface이며 JWT만을 저장하는 것은 아니다. Client의 application에서 필요한 어떤 종류의 string data이든지 저장할 수 있다.

How local store actually work?


점선은 browser 자체를 의미한다. 사용자가 website와 interact하는 interface가 있고 여기에는 여러 탭이 존재한다. 각각의 탭들은 HTML, JS, CSS를 렌더링 한다. 이것은 웹사이트가 어떻게 보여질지와 JS를 통해 locally하게 실행될 수 있는 actions을 말한다.

Local storage는 보편적인 browsers에서 제공되는 interface이다. JS를 통해서 persistent memory 내에서 데이터를 유지한다. Python 딕셔너리와 유사하게 key가 있고 그에 따른 value가 존재한다.

Web brower의 Local store은 두 개의 key 특성을 나타낸다. 하나는 domain specific하다는 것이다. 만약 domain이 udacity.com에서 제공되는 website라면 브라우저에서 내에서 동일한 local store에만 접근한다. 유사하게 google.com은 오직 이것의 local store에만 접근한다. 하지만 두개의 local store는 disjoint하다. google.com이 udacity.com의 local store에 접근할 방법은 존재하지 않는다. 반대도 마찬가지이다.

Local store는 또한 persistent하다. 이것은 만약 사용자가 웹사이트를 떠났다가 나중에 돌아오거나 탭을 닫았다가 다시 열어서 웹사이트에 접속해도 그들이 웹 브라우저의 메모리에 저장되어 있다는 것을 의미한다.

Storing JWTs

Using Javascript to Store JWTs

JWT를 저장하고 가져오기 이전에 공백이 존재할 수도 있다. 사용자가 컴퓨터를 떠났다가 나중에 다시 돌아오거나 tab을 닫는 경우나 다른 일을 하는 경우이다. 결국 JWT가 검색 및 저장되는 시간과 서버로 전송 된 시간 사이에 JWT가 만료되지 않는 한 문제가 없다.

Local store를 사용해서 JWT를 저장하기 위해서는 브라우저에서 제공되는 JS interface를 사용해야 한다.

jwt = response.jwt
localStorage.setItem("token", jwt)

localstorage.setItem에는 key로서 입력된 token과 response에서 받은 jwt가 local store 내에서 token을 설정한다.

이것은 front-end frame work(i.e. reactor)나 HTML의 script element에서 실행 가능하다.

JWT를 사용할 준비가 되었다면 localstore.getItem에서 이전에 사용했던 동일한 key를 사용하여 store로 부터 JWT를 호출 해야한다.

jwt = localStorage.getItem("token")

이제 우리는 JWT string을 JavaScript의 jwt 변수 내에 가지고 있는 것이다. Server에 request를 만들때 request와 함께 이 string을 전달하기 위해 이 변수(jwt)를 사용할 수 있다.

Security Consideration of Local Storage

What could go wrong?

Local stroage와 연관된 고질적인 위험이 존재한다. Local storage는 domain-sepcific하여 다른 wibsite에서는 local store에 접근할 수 없다. 하지만 이것은 악성 공격에 의해 접근이 가능해진다.

Cross-site script(XSS)와 같은 이러한 유형의 공격에는 client가 직접 웹사이트에서 실행할 수 있는 외부 코드를 웹 사이트에 주입하는 것이 포함된다.

우리 웹사이트의 client 코드에 스크립트를 삽입할 수 있는데, 이 스크립트는 local store 내의 모든 키에 접근하여 악성 서버에 떨어뜨린다. Local store에 저장된 우리의 JWT는 유효하고 신뢰하는 auth service에 의해 signed 되었기 때문에 이 악성 서버는 이제 완전히 유효한 credential을 갖게 된 것이다. 또한 local store는 보편적으로 사용되는 테크닉이며 모든 브라우저에 걸쳐 표준화 되어있기 때문에 여러 웹사이트에서 사용할 수 있으며 간단하다.

How Cross-Site Scripting Attcks(XSS) are Performed and Mitigated Techniques

(Mitigate: make less severe, serious, or painful.)

위에서 언급한 종류의 공격은 모든 js 변수들과 interface들을 공격자에게 열어준다. DOM과 rendered HTML까지 열어서 사람들이 그 정보를 악성 서비스에 scrape하고 pull하는 것을 가능하게 한다. 최악의 경우에는 이러한 공격이 버튼이나 form과 같은 새로운 HTML DOM 요소들을 을 주입하여 사용자를 속이고 남이 가져서 안되는 정보까지 제공 받을 수도 있다. 이 정보는 바로 attacker에게 전달되고 더이상은 손 쓸 방법이 없다.

이 공격이 수행되는 한가지 방법은 unsanitized한채로 랜더되는 HTML input을 사용하는 것이다. 예를들어 가장 좋아하는 책을 쓰는 공란이 있다면 사람들은 보통 문자를 입력할 것이다. 하지만 attacker는 이 공간에 다음과 같이 JS를 입력할 수도 있다.

이것은 우리의 요소들을 store에서 가져올 수 있고 이것을 그들의 서버로 전송할 수 있다.

어떤 종류의 JS든 이 form 안에 입력될 수 있으며 이 form이 sanitized되지 않았다면 이것은 사용자의 스크린에 출력될 때 실행될 것이다. 그대신 우리는 input을 sanitize하고 탈출하여 그것이 스크린에서 렌더 되었다고해도 JS를 실행하지는 않고 form input에 적힌 그대로가 렌더 될 것이다.

Input Sanitation은 <과 같은 문자를 &lt;로 변환하며, 이는 코드로 해석되지 않으며 text로 출력된다(<). 이 단계는 항상 서버에서 수행하여 누군가가 Curl 또는 Postman을 사용하여 서버로 악의적인 텍스트를 직접 보내지 못하도록 해야 한다.

이 공격이 수행되는 다른 방법은 다른 웹 사이트에서 호스팅하는 타사 파일을 손상시키는 것이다. 웹사이트에서 제 3자의 service들을 쓰는 것은 매우 흔하다. 이것들은 우리가 알지 못하게 hijacked(납치)되어 crosssite scripting attack code를 포함하도록 손상되고 마치 원래 우리의 웹 client 인 것처럼 웹 사이트에서 실행된다. 때문에 이러한 공급 업체를 심사 할 때는 각별히 주의해야 한다.

마지막으로 우리의 softwar에 매우 많은 dependencies들을 사용하게 된다. 우리는 때때로 NPM에서 맹목적으로 이것들을 설치할 것이다. 이러한 경우에는 사용할 패키지가 믿을만한 개발자로부터 maintained, vetted된 것인지를 확인해야 한다.

NPM 또는 Node Package Manager에 대해 언급했다. 이것은 Javascript 프로젝트에서 사용할 수 있는 공개적으로 제출 된 라이브러리의 온라인 데이터베이스이다. 이러한 패키지가 라이센스 및 보안 정책을 준수하고 보안 취약성을 모니터링 하도록 주의를 기울여야 한다.

또한 local store의 JWT를 사용하기 위해서는 몇가지 룰들을 따라야한다.

첫번째, JWT안에 민감한 정보를 절대 저장하지 않는다. 우리는 JWT가 손상될 것임을 예상해야한다. 만약 손상되었다면 secret이나 public key를 변경하여 이후의 verification step이 실패하게끔 할 수 있다. Payload는 base64 알고리즘을 사용하는 누구에게서나 decode될 수 있음을 기억하라.

두번째, JWT는 자주 만료되어야 한다. 그래서 만약 손상되었다고 해도 누군가는 제한된 시간만을 가지게 된다. 이것은 몇시간이나 며칠이 아닌 몇시간 단위로 설정되어야 한다. 대신 우리의 시스템은 자동적으로 token을 refresh해야 한다.

JWT와 함께 로컬 스토리지를 사용하는 것에 대한 대안도 있다. 우리가 로컬 스토리지를 선택한 이유는 domain-specific하고 persistent하기 때문이다. 이러한 속성은 쿠키에서도 나타난다. 쿠키도 domain-specific하며 브라우저의 새로 고침 및 재설정에도 유지된다(persistent). 또한 HTTP 전용 플래그가 켜져있을 때만 JavaScript에 액세스 할 수있는 추가 속성도 존재한다. 이것은 우리 자신을 포함한 JavaScript가 클라이언트의 해당 토큰에 액세스 할 수 없음을 의미한다. 브라우저는 쿠키를 받을 때 쿠키를 저장하는 것부터 subsequent requests와과 함께 쿠키를 보내는 것까지 모든 것을 처리하게 된다.

profile
지금 있는 곳에서, 내가 가진 것으로, 할 수 있는 일을 하기 🐢

0개의 댓글