data life

[팀프로젝트] 로그인(Login) 구현(2) - JWT 인증 어떻게 사용해야 할까? 본문

회고록

[팀프로젝트] 로그인(Login) 구현(2) - JWT 인증 어떻게 사용해야 할까?

주술회전목마 2023. 6. 21. 00:03

앞서 jwt에 대한 개념들과 구현해야 될 것들을 정리하는 시간을 가졌었다.

이를 토대로 구현을 해보면 되지만 사실 보안과 관련해서 고려해야할 사항들도 굉장히 많았다. 

 

인증 유지

말 그대로 사용자가 로그인 상태를 계속 유지하도록 해주는 개념입니다. 인증 유지를 통해서 화면이 전환될 때마다 매번 로그인해야되는 번거로움을 덜어주고 서버에서 매번 요청에 대해 사용자의 정보를 읽어와서 확인하는 과정을 거칠 필요가 없어집니다. 

따라서, 접속 시에 로그인 과정을 통해 인증 받은 사용자는 사용자의 권한 정보 등을 쉽고 빠르게 접근 가능한 방식으로 보관하고 로그인 된 사용자를 식별하는 인증 키를 발급하고 이 인증 키를 이용해서 계속 요청을 보내는 방식인데 사실 요즘 많이 이용하는 방식이기도 하고 어찌보면 당연하지만 서비스를 개발하고 운영하는 입장에서는 굉장히 까다롭다고 볼 수 있을 것 같다.

 

http 환경

데이터를 주고 받을 시, 공개된 http 프로토콜을 사용합니다. 이는 과거에 비해 손쉽게 정보를 가로챌 수 있는 환경에 노출되어 있다고 보면 되는데 사실 http는 프로토콜 특성 자체가 연결을 유지시키지 않아 추가적인 방법이 필요합니다. 그렇기 때문에 인증과 관련해서 신경써야되는 부분이 많은 건 사실!!

 

구분 서버 세션 방식 JWT
인증정보 보관 서버 토큰에 포함시키고 클라이언트가 보관
인증된 정보 노출 여부 노출 ❌ 노출됨
인증정보 무효화 방법 쉽게 가능 복잡한 로직 구현 필요
타임아웃 처리 방식 사용자가 요청을 보내면 계속 연장 한번 발급된 토큰의 타임아웃 시간은 연장 불가 (재발급이 따로 필요)

 

사실 우리가 결정한 로그인 방식은 다음과 같다.

Access Token은 JSON Payload로 받아와 로컬 변수에 저장
Refresh Token은 httpOnly 쿠키로 저장

 

위의 방식을 통해 얻은 고민들은 다음과 같다.

 

🤔 고민 1.
로컬에 저장된 Access Token은 브라우저창이 꺼지거나, 새로고침, 페이지 이동 시 사라지게 되는데 해결 방안은?
🤔 고민 2. 
Access Token이 만료되었을 경우, 어떻게 처리할 건지?

 

 

사실 사용자가 이미 인증되었음에도 불구하고 Access Token의 휘발성 때문에 모든 요청에 대해 AccessToken을 재발급 받는 로직이 추가되어야 하나 했다.

다행히 axios에서 모든 요청에 대해 hook을 설정할 수 있는 기능이 있어 axios를 통해 API 요청을 하게 되었다.

 

추가로 Refresh 토큰을 쿠키에 보관하기 때문에 HTTP Request에 쿠키 값을 함께 전달해야한다.

쿠키 값을 함께 전달하기 위해서는 withCredentials 옵션을 true로 설정해주어야 함!!

 

 

토큰 탈취해서 정리한 부분은 다음과 같다.

 

👿 XSS (Cross-site Scripting)

: 브라우저의 로컬 스토리지나 쿠키 정보를 해커의 사이트로 보낸다.

=> 최근에는 사이트 보안 수준이 높아져서 사용자가 입력한 스크립트 포함된 글에 대해 보안 방지 처리를 하고 있다

 

👿 CSRF (Cross-site Request Forgery)

: 토큰 탈취가 아닌 현재 사용중인 사용자가 다른 액션을 처리하게 한다.

 

  엑세스 토큰 리프레시 토큰
XSS 노출  노출되면 안됨 노출되면 안됨
CSRF 노출  노출되면 안됨 노출해도 됨 
(새로 발급하기 위한 토큰이므로)
데이터 유지 적당히(?) 로그아웃 전까지는 정해진 시간 내에 브라우저에서 삭제되면 안됨
적합한 저장소 자바스크립트 내 변수
- 쿠키나 스토리지가 아니기 때문에 외부 스크립트에서 사용 불가 (XSS 방어 가능)
- 쿠키가 아니므로 해커에 의한 자동요청 전송 시에도 CSRF 방어 가능
- HttpOnly : 스크립트에서 사용 불가
- Session : 브라우저 종료 시, 자동 삭제
- Secure 설정된 쿠키 : Https에서만 전송

 

 

이제 accessToken이 만료되었을 경우에는 어떻게 처리해야될지 2가지 방법을 고민했었다.

1. 다시 로그인하도록 로그인 페이지로 이동

2. 유저가 모르게 새로운 accessToken을 받아와 로그인 연장하도록 기능

 

(현재는 2번 방법을 채택하였다.)

 

 

 

사실, jwt 방식이 많이 쓰이지만 그만큼 100% 완벽하다고 볼 수는 없는 것 같다. 보안과 유저의 사용성에 대해서 적절한 상호보안점을 맞추는 게 굉장히 중요하다고 깨달았던 고민의 시간들(?)이었다. 그래서 로그인 구현에 있어서 굉장히 많은 시간을 들였는데 어떠한 방법이 정답이라고는 말할 수 없을 것 같고 그냥 사용하고자 하는 인증 유지 방법과 동작원리를 잘 이해하고 어느 정도까지 허용할 것인가 선택의 사항이라고 생각하며! 진짜 소셜로그인으로 돌아오겠음!