[TIL] 22.01.04 Access token 과 Refresh token

hyewon jeong·2023년 1월 4일
1

TIL

목록 보기
61/138
post-thumbnail

1 . 문제점

AccessToken과 RefreshToken 함께 사용하여 토큰을 이중 장막을 쳐서 보다 보안을 강화하는 식을 적용하는 부분에 있어

💘이때 , RefreshToken도 함께 업데이트를 매번 해줄 것인지 , 아니면 RefreshToken 만료시점에 별도로 잘 발행 하는게 답이냐 의견 충돌이 생김

2 . 시도한 점

튜텨님께 여쭤보기

3 . 해결

AccessToken 만료 되면 만료신호를 보내어
RefreshToken을 가지고 AccessToken발급 요청하게 되고
DB에 저장된 RefreshToken과 가져온 RefreshToken 일치하는지 확인 후
AccessToken을 재발행하게 되는데 ,

💘이때 , RefreshToken도 함께 업데이트를 매번 해줄 것인지 , 아니면 RefreshToken 만료시점에 별도로 재발행 할것인지가 포인트인데

정답은 없다. 둘다 상황에 따라 선택하여 적용하면 된다.
만약 AccessToken 재발행 동시에 RefreshToken도 같이 재발행이 된다면
자주 사용하는 웹 일경우 로그인할시간이 재발행수만큼 연장시간도 늘어나 사용자가 로그인 없이 편하게 웹을 사용할 수 있는 이점이 있다.

4 . 알게 된점

  • 앱의 경우 폰마다 보안저장소가 따로 있어 보안저장소에 토큰을 저장하는 방법이 있다.

JWT 의 장점

  1. 클라이언트 인증 정보를 저장하는 세션과 다르게, 서버는 무상태(StateLess)가 되어 서버 확장성이 우수해질 수 있다.
  2. 인증 정보에 대한 별도의 저장소가 필요없고, DB쿼리문을 수시로 날리지 않아도 되어 DB의 부하를 감소시킨다.
  3. 토큰 기반으로 다른 로그인 시스템에 접근 및 권한 공유가 가능하다. (쿠키와 차이)

💥위와 같이 JWT는 인증정보에 대한 별도의 저장소가 필요없는데..
RefreshToken을 DB에 저장한다라는 건 모순 되는 점!

이 부분에 대해 다시 공부가 필요하다.

5 . 기타 공부


1. 사용자가 ID, PW를 입력하여 서버에 로그인 인증을 요청한다.
2. 서버에서 클라이언트로부터 인증 요청을 받으면, Header, PayLoad, Signature를 정의한다.
Hedaer, PayLoad, Signature를 각각 Base64로 한 번 더 암호화하여 JWT를 생성하고 이를 쿠키에 담아 클라이언트에게 발급한다.
3. 클라이언트는 서버로부터 받은 JWT를 로컬 스토리지에 저장한다. (쿠키나 다른 곳에 저장할 수도 있음)
API를 서버에 요청할때 Authorization header에 Access Token을 담아서 보낸다.
4. 서버가 할 일은 클라이언트가 Header에 담아서 보낸 JWT가 내 서버에서 발행한 토큰인지 일치 여부를 확인하여 일치한다면 인증을 통과시켜주고 아니라면 통과시키지 않으면 된다.
인증이 통과되었으므로 페이로드에 들어있는 유저의 정보들을 select해서 클라이언트에 돌려준다.
5. 클라이언트가 서버에 요청을 했는데, 만일 액세스 토큰의 시간이 만료되면 클라이언트는 리프래시 토큰을 이용해서
6.서버로부터 새로운 엑세스 토큰을 발급 받는다.

Tip

💡 JWT은 서명(인증)이 목적이다.
JWT는 Base64로 암호화를 하기 때문에 디버거를 사용해서 인코딩된 JWT를 1초만에 복호화할 수 있다.
복호화 하면 사용자의 데이터를 담은 Payload 부분이 그대로 노출되어 버린다. 그래서 페이로드에는 비밀번호와 같은 민감한 정보는 넣지 말아야 한다.
그럼 토큰 인증 방식 자체가 빛 좋은 개살구라고 생각할수도 있지만, 토큰의 진짜 목적은 정보 보호가 아닌, 위조 방지이다.
바로 위에서 소개했듯이, 시그니처에 사용된 비밀키가 노출되지 않는이상 데이터를 위조해도 시그니처 부분에서 바로 걸러지기 때문이다.

Tip

서버에서 가장 피해야 할 것은 데이터베이스 조회이다.
서버 자체가 죽는 경우도 있지만, 대부분 DB가 터져서 서버도 같이 죽는 경우가 허다하기 때문이다.
이런 점에서, JWT 토큰은 DB조회를 안해도 되는 장점을 가지고 있다는 점이다.
만일 payload에 유저이름과 유저등급 을 같이 두고 보내면, 서버에서는 유저이름을 가지고 DB를 조회해서 유저 등급을 얻지않아도 바로 원하는 정보를 취할수 있다.

JWT의 Access Token / Refresh Token 방식

다만 이 JWT도 제 3자에게 토큰 탈취의 위험성이 있기 때문에, 그대로 사용하는것이 아닌 Access Token, Refresh Token 으로 이중으로 나누어 인증을 하는 방식을 현업에선 취한다.

Access Token 과 Refresh Token은 둘다 똑같은 JWT이다. 다만 토큰이 어디에 저장되고 관리되느냐에 따른 사용 차이일 뿐이다.

Access Token : 클라이언트가 갖고있는 실제로 유저의 정보가 담긴 토큰으로, 클라이언트에서 요청이 오면 서버에서 해당 토큰에 있는 정보를 활용하여 사용자 정보에 맞게 응답을 진행
Refresh Token: 새로운 Access Token을 발급해주기 위해 사용하는 토큰으로 짧은 수명을 가지는 Access Token에게 새로운 토큰을 발급해주기 위해 사용. 해당 토큰은 보통 데이터베이스에 유저 정보와 같이 기록.
개념이 생소할수 있지만 Access Token은 우리가 지금까지 설명한 JWT를 말하는 것이라고 보면 된다.

정리하자면, Access Token은 접근에 관여하는 토큰, Refresh Token은 재발급에 관여하는 토큰의 역할로 사용되는 JWT인 것이다.

위에서도 말했듯이 JWT 인증 방식을 만약 Access Token 만을 이용하면, Access Token은 발급된 이후 서버에 저장되지 않고 클라이언트에 저장되어 토큰 자체로 검증을 하며 사용자 권한 인증을 진행하기 때문에, Access Token이 탈취되면 토큰이 만료되기 전 까지, 토큰을 획득한 사람은 누구나 권한 접근이 가능해지는 문제점이 있었다. 그래서 토큰의 유효 시간을 부여하여 탈취 문제에 대해 대응을 하기도 하지만, 만일 유효 기간이 짧을 경우 그만큼 사용자는 로그인을 자주해야 하는 번거로움이 있다.
따라서 이러한 문제를 해결하기 위해 Refresh Token 이라는 추가적인 토큰을 활용하여 토큰을 이중 장막을 쳐서 보다 보안을 강화하는 식으로 보면 된다.

Access / Refresh Token 재발급 원리

1. 기본적으로 로그인 같은 과정을 하면 Access Token과 Refresh Token을 모두 발급한다.

이때, Refresh Token만 서버측의 DB에 저장하며, Refresh Token과 Access Token을 쿠키 혹은 웹스토리지에 저장한다.

2. 사용자가 인증이 필요한 API에 접근하고자 하면, 가장 먼저 토큰을 검사한다.

이때, 토큰을 검사함과 동시에 각 경우에 대해서 토큰의 유효기간을 확인하여 재발급 여부를 결정한다.

📢case1 : access token과 refresh token 모두가 만료된 경우 → 에러 발생 (재 로그인하여 둘다 새로 발급)
📢case2 : access token은 만료됐지만, refresh token은 유효한 경우 → refresh token을 검증하여 access token 재발급
📢case3 : access token은 유효하지만, refresh token은 만료된 경우 → access token을 검증하여 refresh token 재발급
📢case4 : access token과 refresh token 모두가 유효한 경우 → 정상 처리

Tip

[refresh token을 검증하여 access token 재발급]
클라이언트(쿠키, 웹스토리지)에 저장되어있는 refresh token과 서버 DB에 저장되어있는 refresh token 일치성을 확인한 뒤 access token 재발급한다.

[access token을 검증하여 refresh token 재발급]
access token이 유효하다라는 것은 이미 인증된 것과 마찬가지니 바로 refresh token 재발급한다.

3. 로그아웃을 하면 Access Token과 Refresh Token을 모두 만료시킨다.

Refresh Token 인증 과정

RefreshToken-AccessToken
1. 사용자가 ID , PW를 통해 로그인.

  1. 서버에서는 회원 DB에서 값을 비교

3~4. 로그인이 완료되면 Access Token, Refresh Token을 발급한다. 이때 회원DB에도 Refresh Token을 저장해둔다.

  1. 사용자는 Refresh Token은 안전한 저장소에 저장 후, Access Token을 헤더에 실어 요청을 보낸다.

6~7. Access Token을 검증하여 이에 맞는 데이터를 보낸다.

  1. 시간이 지나 Access Token이 만료됐다.

  2. 사용자는 이전과 동일하게 Access Token을 헤더에 실어 요청을 보낸다.

10~11. 서버는 Access Token이 만료됨을 확인하고 권한없음을 신호로 보낸다.

Tip

Access Token 만료가 될 때마다 계속 과정 9~11을 거칠 필요는 없다.
사용자(프론트엔드)에서 Access Token의 Payload를 통해 유효기간을 알 수 있다.
따라서 프론트엔드 단에서 API 요청 전에 토큰이 만료됐다면 곧바로 재발급 요청을 할 수도 있다.

  1. 사용자는 Refresh Token과 Access Token을 함께 서버로 보낸다.

  2. 서버는 받은 Access Token이 조작되지 않았는지 확인한후, Refresh Token과 사용자의 DB에 저장되어 있던 Refresh Token을 비교한다. Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 발급해준다.

  3. 서버는 새로운 Access Token을 헤더에 실어 다시 API 요청 응답을 진행한다.

출처 :https://inpa.tistory.com/559

profile
개발자꿈나무

0개의 댓글