dev_man
62
2020-09-26 11:13:27
6
229

프론트엔드 JWT 토큰 저장


rest api 프로젝트에 JWT 를 사용하려 합니다. 

백엔드에서 발행 해주는 accessToken, refreshToken 값을 

프론트엔드 어느곳에 저장하여야 하는지 선택해야 되더라구요. 


구글링한 결과 

JWT 토큰을 프론트 엔드 에서 저장하는 방법 

  1. local storage 

      -> xss 공격에 취약 

  2. Cookie(httponly secured) 

      -> CSRF 공격에 취약 


 위에 두가지 방법중에 cookie 를 선택후 CSRF 방어로직 추가 하기로 결정했습니다. 

CSRF 방어로직 방법 

Spring security 를 사용하여 처리 

//security 설정
... 
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
...

1)  security에서 csrf 값을 쿠키로 생성해서 프론트에 전달

2)  프론트에서 쿠키에서 CSRF 값 헤더에 추가하여 API 호출 

3)  서버에서는 쿠키에 JWT 값 읽어서 처러 , CSRF 는 security 필터 에서처리  


요약하면 

서버

  - jwt token  값 쿠키(httpOnly secured) 로 전달  

  - csrf  값도 쿠키(httpOnly= fale)로 전달 

프론트 

  - csrf 쿠키에서 값 읽어서 헤더에 설정후 api 호출 


위와 같이 구성하려고 하는데 추가적으로 고려할 사항이 있을까요? 



1
  • 답변 6

  • 성일
    567
    2020-09-26 18:56:22

    일단은 괜찮은듯. httpOnly를 꺼둘 필요가 있나요

  • dev_man
    62
    2020-09-26 22:44:21

    답변감사합니다! 

    csrf 에서만 httpOnly = false한거는  프론트에서 자바스크립트로  쿠키값읽어서 헤더에 심어주려고 설정했습니다.~

  • 성일
    567
    2020-09-27 13:23:17

    좋지 않은듯. 쿠키를 바로 입력할 수 있도록 백엔드에서 set-cookie 옵션을 쓰세요. 아니면 관련 라이브러리를 백엔드에서 처리하거나. 이 방식은 (제가 이해하기론) 프론트로 쿠키 관련 정보를 받은 뒤 js로 프론트 쪽에서 쿠키값을 저장하는 식인데, 중간에 js를 임의로 막을 수 있습니다 개발자 도구로요


    굳이 보안 부분을 강조하고 싶은 것 같아서 첨언해봤습니다.

  • dev_man
    62
    2020-09-27 15:00:16

    피드백 감사합니다~

    성일님 말씀대로 쿠키는 백엔드에서 setCookie 해주고 있습니다

    Jwt 쿠키는 httpOnly라서 프론트에서 요청시 자동으로 들어오게 처리예정입니다. 

     그러면 csrf공격에 위험하니, 서버에서 csrf 토큰값을 js 로 읽을수 있게 쿠키를  httpOnly=false 생성해줍니다. 

    성일님이 피드백 주신게 csrf 쿠키값을 js로 막을수 있다는 부분인거 같습니다.

    csrf 값을 변조하거나 막아서 api 요청하면 서버에거 csrf 값이 서버에서 생성해준 값인지 비교를 하고있어서 오류를 응답으로 내려주게 되어있습니다.

    결국 api 자원을 보호할수 있을것 같습니다.

    이렇게 피드백 주시니 좀더 제가 하려는것에 대해 한번더 정리 할수 있게 되네여. 감사합니다!






  • 성일
    567
    2020-09-27 15:58:48

    csrf 체크를 백엔드에서 하는게 더 자연스럽습니다. 지금 말씀하신걸 다 이해하지는 못했는데 프론트에서 일부 보안을 담당하는 것처럼 느껴지네요. 


    기본적으로 모든 보안로직은 최대한 백엔드에 힘을 싣는게 좋습니다. 


    새로 코멘트 주신 거 포함해서, 저는 왜 모두 setcookie 하면 안되는지 모르겠습니다!

  • dev_man
    62
    2020-09-27 18:45:37

    정리하면 제가 말씀 드린 거 또한 백엔드에서 쿠키생성(setCookie)을 하고, 백엔드에서 검증을 하게 됩니다. 

    1. 백엔드(spring boot)  쪽에서 JWT 토큰 쿠키생성(HttpOnly secured) 

        - 브라우저에서  js를 통해 JWT쿠키 접근불가함 

       -  https 환경에서 api 요청시 서버에 쿠키값이 자동전달됨

       - 서버에서 JWT 파싱해서 권한확인 

    아마 위의 내용은 이해하셨을 것 같습니다. 


    2. CSRF 방지 위해 백엔드 쪽에서 CSRF 값을 담은 쿠키생성(HttpOnly = false)

     CSRF 토큰은 왜 HttpOnly 안해주나, 브라우저에서 JS로 접근이 가능하게 된다. 

     이부분이 의문이신거 같네요. 


    아실수도 있는 내용일거 같은데  CSRF 공격을 잠깐 설명드리면

    제가만든 사이트가 A라고하면, 

    1. 브라우저에서 A사이트 로그인 => JWT 쿠키 생성됨 

    2. 그 상태로 B사이트 접속 =>  숨겨진 form 으로 A사이트  데이터 변경 API 호출(브라우저에 JWT 쿠키가 존재하므로 JWT 값 자동전송됨)  

    3. B사이트에 숨겨진 form 요청에 정상응답(JWT쿠키가 제대로 된 데이터이므로 정상처리)


    이런 시나리오에 대한 방어를 위해 CSRF  토큰을 활용하기로 했습니다. 

     1)  CSRF 쿠키도 httpOnly로 할경우

        B 사이트에 숨겨진 폼으로 A 사이트 API 요청시 CSRF 값도 같이 자동전송되 백엔드에서 생성해준 임의랜덤 문자열과 같게 돼서 정상처리 됩니다.

    2) CSRF 쿠키를 httpOnly = false 후  프론트에서 쿠키값 읽어서  js로 헤더에 csrf에서 생성된 랜덤문자열 받아서 검증 

      - 백엔드에서 http 요청에 헤더 값을 뒤져서 CSRF 값을 참조 해서 정당한 요청인지 확인 

      - B 사이트에서 숨겨진 폼으로 A사이트 API 요청해도, JWT 값만 전달 되고 CSRF 값은 전달이 안되서 

    호출된 API에 401응답이 내려옴 


    위에 같은 이유로 성일 님이 말씀하신  보안로직 처리는 백엔드(spring security 활용) 에서 이루어지고 있습니다. 

    역시 설명하는 글을 쓰기에는 쉽지 않네요 -_-;    

  • 로그인을 하시면 답변 을 등록할 수 있습니다.