JWT에 대한 고민

햐얀하늘·2024년 7월 15일
0

JWT

1. JWT 사용시 고민해 볼 것들

  • 동시에 유저가 동일한 아이디로 접속시 token발급 어떻게 처리할 것인가?
    • 동시 접속 제한
    • 동시 접속 허용
  • 토큰 저장
  • 토큰 탈취(보안) :
    • accessToken 탈취
    • refreshToken 탈취
    • secretKey 탈취
  • 토큰 무효화:

2. 고민 정리하기

1. 동시 접속 허용 시 token 발급방법:
동시 접속을 허용 한다면 각 유저들에게 동일한 아이디로 접속 시 매번 새로운 토큰을 발급해준다.

why?

  • 동시 접속을 허용하기 때문에 클라이언트 각자 자신의 AccessToken을 활용해 인증인가를 진행해야한다. 만약 동일한 토큰을 저장해서 유저들에게 준다면 특정 유저는 늦게 접속해 5분, 3분 등 유저들이 AccessToken을 활용할 시간이 제한될 수 있다.
  • 만약 동일한 아이디를 사용하는 모든 유저들이 하나의 AccessToken만을 써야할 때 어떤 기준으로 토큰을 줄 것인가?
    처음 접속한 유저가 생성한 토큰을 후에 접속한 유저들에게 전달 => 각 유저들에게 accessToken의 시간의 효율이 다 달라 불편함 / token을 따로 서버에서 저장해 관리해야함 stateless 불가
    유저가 접속했을 때 마다 토큰을 생성해서 모든 유저들에게 다시 전달 => 모든 유저들에게 새롭게 발급된 token을 새로 전달해야함(sse, rabitMQ 활용)
    즉 어떤 토큰을 유저에게 줄 것인지 기준을 정하기 어렵고 비효율적이다.

해결책

  • 유저가 접속할 때마다 새로운 AccessToken을 발급해 전달한다.

why?

AccessToken을 유저마다 가지고 있어 만료시간 등의 관리가 편함. 굳이 서버에서 관리를 위해 저장할 필요가 없음. 새로운 토큰에 대한 정보를 클라이언트끼리 공유 필요가 없다.

만약 동시접속을 허용할 시 JWT 토큰은 각 유저들에게 새로운 토큰을 발급해 전달하는 것이 가장 효율적!!!

2. 동시 접속 제한 시 Token 발급방법:

  1. 현재 접속한 유저가 존재하면 새 토큰발급 제한(즉 새로운 유저 접속 불가)
    • Redis에 현재 접속한 유저의 아이디를 accessToken 만료 시간 만큼 설정해 저장 -> 새로운 유저가 동일한 아이디로 접속시 redis체크하여 동일한 아이디가 존재하면 접속 차단 => redis에 유저 정보를 저장해야함
    • user db에 최근 접속 시간에 대한 정보 저장 -> 로그인 할 때마다 최근 접속 시간과 현재시간을 비교해 Token의 만료시간이 지났는지 확인 / 유저의 접속 상태를 1, 0으로 DB에 저장해서 0일때만 토큰 발급하도록
  2. 현재 접속한 유저의 토큰을 만료시키고 새로운 유저에게 새 토큰을 발급 - TokenBlacklist
    • redis나 캐시에 현재 사용되는 토큰과 유저정보 매핑해 저장 -> 새로운 유저 접속 시 해당 유저정보에 맞는 AccessToken redis에서 꺼내서 redis에 TokenBlackList에 저장 => token stateless 불가 / 새로운 유저 접속 시 기존 유저 로그아웃 시키기
    • 세션이나 DB에 유저의 토큰을 저장해서 로그인 할때마다 기존 토큰 삭제하고 새로운 토큰 집어넣기

3. 토큰 저장

JWT의 강점은 stateless 즉 서버측에서 저장하지 않아도 된다는 것이 가장 큰 장점이라고 생각했다. 그래서 DB, 세션 등을 활용해 저장하는 것은 JWT를 쓰는 이유중 큰 장점을 상쇄한다고 생각했기 때문이다.

하지만 결국 다중 접속, 동시 로그인 제한 등의 상황을 제어하기 위해서는 저장이라는 것은 필수적이라 생각한다.

stateless에 사로잡혀서 jwt 왜 쓰는거지? 어차피 session이나 redis, db로 관리할 거면 굳이 쓸 필요가 있나?? session 로그인 방식이 더 편한거 아닌가? 생각했었는데 무결성 체크, 확장성, MSA 등에서는 세션보다 더 큰 장점이 있다 생각했다.

그래서 대규모 서비스에서는 확장성과 세션의 메모리 문제 등의 조건때문에 JWT를 다수 사용하는 것이라 생각한다. 만약 소규모 프로젝트라면 굳이 JWT를 쓰는 것이 의미가 없을것 같다. 차라리 세션방식을 통해 관리를 하는 것이 더 의미있는것 같다.

4. 토큰 탈취

  1. accessToken 보안(탈취 대응 및 예방)
  • refreshToken 만료시키기(DB 삭제 or blacklist 추가)
  • accessToken 블랙리스트 추가
  • IP payload로 등록 후 IP변화 시 알림 및 token lock걸기
  • 다중접속, 다른 위치, OTP 등을 활용해 특이사항 발생 시 알림
  1. refreshToken 보안
  • 로그인 접속할 때마다 refreshToken 재발급
  • accessToken과 같이 위의 내용과 비슷하게 대처가능
  1. secretKey 탈취
  • 주기적으로 교환 -> 모든 유저 로그아웃 처리 필요
  • OTP 등 2차 인증 시스템

5. 토큰 무효화

accessToken과 같은 경우 로그아웃 하더라도 accessKey를 가지고 있으면 만료되기 전까지 사용이 가능하다. 그래서 해당 accessToken을 무효화 하는 코드가 필요하다.

  1. blacklist 추가
  2. db, redis 등에 무효화 토큰 저장 => 오래된 db내용은 주기적으로 삭제 필요(스케쥴링)
  3. 토큰 생성날짜/토큰버전 등의 값을 DB에 저장해 token의 버전과 받은 토큰의 생성날짜나 버전정보를 비교해 이전 토큰이면 무효화시키기
profile
나는 커서 개발자가 될거야!

0개의 댓글