JWT인증 유지란?인증 유지는 왜 까다롭나?HTTP 이전 환경HTTP 시대많이 사용하는 인증 유지 방법서버 세션 방식JWT(Json Web Token) 방식세션 방식과 JWT 방식의 차이는?인증정보 보관 장소인증된 정보 노출 여부인증 정보의 무효화 방법타임아웃 처리 방식JWT 사용 시 보안적으로 고려해야 할 사항Access Token, Refresh Token 이중 토큰 사용토큰 탈취 관련
JWT
- MSA가 많이 보급되면서 클라이언트와 서버 간의 인증 상태를 유지하는 기존의 전통적인 서버 세션 방식과 다른 클라이드 사이드 세션인 JWT(Json Web Token) 방식이 많이 활용되고 있다.
세션방식과 JWT방식은 어떤 차이가 있으며 마이크로 서비스에서는 왜 사용되는지 보안적으로 어떤 고려사항이 있는지 정리해보자 !
인증 유지란?
- 일반적인 서비스의 경우 백엔드 서버에서 특정 사용자의 주문 처리, 주문 목록 전달 등과 같이 로그인 사용자 또는 그 사용자의 권한에 맞는 정보를 제공하거나 로직을 처리하게 된다.
- 인증 유지란 사용자가 한번 로그인 한 이후 특정 시간 내에는 다시 로그인하지 않아도 사용자의 로그인 상태를 계속 유지하는 개념이다.
- 인증 유지 개념이 없는 시스템이라면 화면이 전환될 때 마다 매번 로그인을 하거나 서버에서는 매번 요청에 대해 사용자가 요청을 처리할 권한이 있는지 확인하는 과정을 거쳐야 한다.
- 대부분의 서버는 처음 접속 시 로그인 과정을 통해 인증 받은 사용자는 사용자의 권한 정보 등을 메모리 등 쉽고 빠르게 접근 가능한 방식으로 보관하고, 로그인 된 사용자를 유일하게 식별할 수 있는 인증 키 등을 발급하고, 이 인증 키 정보를 이용해서 계속 요청을 보내는 방식을 사용한다.

인증 유지는 왜 까다롭나?
HTTP 이전 환경
- 클라이언트가 바이너리 형태로 배포되는 독립적인 애플리케이션의 클라이언트와 이 클라이언트에 전용으로 대응하는 서버 시스템의 경우 클라이언트 - 서버간의 요청에 대한 규격이 표준화 되지 않았다.
- 시스템을 구성하는 측에서 임의로 정했기 때문에 어떤 방식으로 인증하는 지에 대해서는 외부에 노출되는 경우가 드물었다.
- 클라이언트 - 서버 이전의 환경도 보면 클라이언트에는 로직을 처리하거나 인증 키 같은 데이터를 저장할 수 있는 기능이 없고 단순히 모니터와 키보드로 구성된 형태이기 때문에 인증 유지 개념보다는 연결 유지 개념이 더 강했다고 말할 수 있다.
- 최근에는 웹이 아닌 앱의 경우 클라이언트/서버 형태의 시스템이라고 할 수 있다. 하지만 애플리케이션과 백엔드 서버 사이의 주요 통신은 공개된 망과 공개된 프로토콜인 HTTP로 처리하고 있기 때문에 전통적인 클라이언트/서버 아키텍처에서 사용했던 방식이 아닌 HTTP 프로토콜에서 처리하는 인증 방식을 주로 사용하고 있다.
HTTP 시대
- 웹 기반으로 시스템 환경이 넘어오면서 가장 큰 특징은 표준화되고, 공개된 기술들을 주로 사용하게 된 점이다.
- 클라이언트는 몇개의 브라우저 또는 앱 위주이고 데이터를 주고 받는 것은 주로 HTTP 프로토콜을 사용하고 있다.
- 인증 유지 관점에서 보면 과거의 컴퓨팅 환경에서는 사용자가 로그인을 하면 연결을 지속적으로 유지시키는 방법이다 보니 한번 연결되면 이후로는 특별한 처리를 하지 않아도 유지가 되었지만 HTTP 프로토콜 특성 자체가 연결을 유지시키지 않기 때문에 추가적인 방법을 통해 인증을 유지시켜야 한다.
- 정보를 가로챌 수 있는 환경에 더 쉽게 노출되어 있고, 별도의 인증 유지 방법을 추가해야 하기 때문에 현재는 시스템 구성시에 인증/세션 등에 대해서 더 신경을 쓰고, 정교하게 다뤄야 하는 상황이 되었다.
많이 사용하는 인증 유지 방법
서버 세션 방식
- 사용자 로그인 시 서버는 사용자 인증을 완료하고, 인증된 사용자는 정보를 접근이 빠른 저장소인 메모리나 캐시 등에 저장한다.
- 서버는 서버에 저장된 사용자 인증 정보의 유일한 키를 발급한다. > 세션키
- 서버는 로그인에 대한 응답으로 세션키를 클라이언트에게 전달한다.
- 클라이언트는 받은 세션키를 클라이언트의 저장공간(쿠키or로컬스토리지)에 저장한다.
- 클라이언트는 서버로 작업을 요청할 때 세션키를 같이 전달한다.
- 서버는 클라이언트 요청에서 세션키를 이용하여 서버에 저장된(메모리) 인증 정보에 있는지 여부와 어떤 사용자의 요청인지 확인한다.
[세션 방식의 보안 이슈]
- 가장 큰 이슈는 세션키가 유출되는 경우이다. 세션키가 유출되면 이 세션키를 이용하여 악의적으로 서버에 요청을 보낼 수 있게된다.
- 세션키가 유출되는 피해를 최소화 하기 위해 세션 만료 시간을 설정한다.
- 세션 유효시간이 1시간인 경우 1시간 이후에 오는 요청은 만료된 요청으로 간주하며 다시 로그인을 유도한다.
- 세션 유효 시간의 기준은 클라이언트로부터 마지막 요청 이후 시간을 사용한다. 이를 위해 서버는 클라이언트로부터 매번 요청에 대해 세션 사용 시간을 계속 갱신한다.
- 세션 정보를 DB에 저장해도 되지만 매번 요청올 때마다 세션 정보를 update 해야하기 때문에 DB에 저장하지 않고 메모리 또는 캐시에 저장한다.
[세션 방식의 MSA 이슈]
- 서버 세션 인증 방식이 가장 많이 사용 되고 일반적인 방법이며 사용자의 권한에 변경이 발생했을 때 즉시 반영할 수 있는 등의 장점이 있다. 하지만 서버 세션 인증 방식의 골치아픈 부분은 서버 대수가 한대 이상으로 구성되는 경우이다
- 서버의 메모리에 세션 정보를 보관하는 경우 사용자가 로그인 시 접속한 서버에만 세션정보가 있기 때문에 사용자가 로그인 이후 다른 서버로 요청을 보내면 세션이 없기 때문에 로그인을 다시해야하는 문제가 있다.
- 이런 문제를 해결하기 위해 추가 방안을 생각해야 한다.
- 특정 사용자의 요청은 동일한 서버로 보내는 방법
- 세션 정보를 서버의 메모리가 아닌 공유 캐쉬 등에 저장하는 방법
- 세션 정보를 모든 서버가 동일하게 가지는 방법 등을 사용할 수 있다.
- 서버 댓수가 많지 않고, 모든 서버가 동일한 기능을 수행하는 모놀리틱 아키텍처 환경에서는 위와 같은 방법을 통해 해결이 가능하지만, 서버 댓수가 많아지고 각 서버의 기술적인 구현체도 다를 수 있는 MSA 환경에서는 쉽게 해결할 수 있는 방법은 아니다.
JWT(Json Web Token) 방식
- 서버 세션 방식과 약간 반대되는 방식으로 구현한 것이 JWT 방식이다.
- 서버에 세션 정보를 저장하지 않고, 로그인 시 클라이언트에게 로그인 사용자 정보가 포함된 토큰을 발행하고, 클라이언트는 서버에 어떤 작업을 요청할 때 마다 토큰을 같이 보낸다.
- 서버는 토큰에 포함된 사용자 정보를 이용하여 인증/인가를 처리하는 방식이다.
- 인증을 유지한다는 개념보다는 인증된 값을 계속 제공한다고 볼 수 있다.
- JWT(Json Web Token)이라는 이름에 있는 Json 명칭에도 알 수 있듯이 Json으로 만들어진 인증 관련 정보를 인코딩한 토큰을 이용하여 인증하는 방식으로 처리된다
[JWT 처리방식]
- 사용자는 로그인 시 서버는 사용자 인증을 완료하고 외부에 노출되어도 문제가 없는 인증관련 정보(사용자 ID, 권한)을 JSON 형태로 만든다.(Payload)
- JSON 형태의 Payload를 base64 방식으로 인코딩하여 문자열을 만들고, 미리 정한 시스템의 SecretKey를 이용하여 서명 문자열을 생성한다.
- Header 정보, 인증 정보(Payload), 서명 문자열을 하나의 문자열로 합친다.
- 서버는 인증 요청에 대한 응답으로 인코딩 된 문자열을 클라이언트로 전달한다.
- 클라이언트는 서버로부터 받은 토큰을 클라이언트의 저장공간(쿠키, 로컬스토리지)에 저장한다.
- 클라이언트는 서버에 요청 시 토큰을 서버로 같이 전달한다.
- 서버는 클라이언트의 요청에서 받은 토큰 값을 이용하여 어떤 사용자의 요청인지 확인한다.
[JWT 장점]
- 가장 큰 특징은 토큰 자체 내에서 이미 인증 관련 정보를 내장하고 있어 서버들 사이에 이 정보를 공유할 필요 없이 이 토큰을 받은 서버는 토큰 정보만을 이용하여 인증을 처리할 수 있다.
- 이 특징 때문에 다른 몇가지 단점이 있음에도 불구하고 MSA 기반의 시스템에서는 많은 관심을 받고 있다.
세션 방식과 JWT 방식의 차이는?
- 전체적은 흐름을 보면 큰 차이는 없지만 실제 사용에 있어서는 큰 차이가 존재한다.
인증정보 보관 장소
- 세션 방식은 서버에 인증정보(세션키)를 저장한다. 따라서 인증된 서버가 아닌 다른 서버에서는 인증 여부를 알 수 없다. > Session 공유 기술 필요
- JWT는 토큰 내에 인증된 사용자의 정보를 가지고 있다. 따라서 요청 받은 모든 서버에서 확인이 가능하다.
인증된 정보 노출 여부
- 인증 완료 후 클라이언트로부터 요청 시 사용할 사용자 정보를 어디에 저장할 것인가?
- 매 요청마다 DB에서 사용자 정보를 조회하면 성능이 좋지 않기 때문에 메모리 등에 보관한 후 다시 사용한다.
- 세션 방식의 경우 인증 정보가 보안이 잘 되어 있는 서버 계층에 보관되기 때문에 정보가 노출 되지는 않는다.
- JWT의 경우 JWT를 발급하는 과정을 보면 사용자 ID, 권한 정보 등이 보관되는 Payload 부분은 암호화가 안되고 평문을 단순히 base64 방식으로 인코딩한 수준이기 때문에 복호화 하는 사이트를 통해 쉽게 어떤 정보가 저장되어 있는지 확인할 수 있다.
- 따라서 Payload에는 노출되어도 무방한 정보만 저장해야 한다. 예를 들어 사용자ID(로그인ID가 아닌 일련번호), 권한명칭, 소속부서ID 등
- Payload 부분을 암호화한 JSON Web Encryption(JWE)를 사용할 수도 있지만 아예 노출이 되지 않는 세션 방식보다는 노출되어 있는 것은 사실이다.
인증 정보의 무효화 방법
- 세션키나 인증정보가 유출된 경우 관리자에 의해 강제적으로 인증 정보를 무효화 시킬 필요가 있지만 세션 방식의 경우 서버에 보관된 세션 정보를 관리자가 임의로 삭제할 수 있다.
- 하지만 JWT의 경우 이미 발급된 토큰에 대해서는 강제적으로 무효화 시키기 어렵다.
- 사용자가 로그아웃 처리 시 웹/앱 등 자신이 로그인 한 모든 단말에서 로그아웃 처리를 원할 경우 JWT 기반인 경우는 어렵다
타임아웃 처리 방식
- 세션은 요청 시 마다 타임아웃 시간이 자동으로 갱신된다. 따라서 사용자가 간헐적으로 요청을 보내고 있으면 세션이 만료되지 않는다.
- JWT의 경우 발급된 토큰 내에 만료 시간을 가지고 있기 때문에 서버는 토큰을 검증하는 과정에서 이 만료 시간을 초과한 경우 유효하지 않은 토큰으로 간주한다.
- JWT 토큰 만료 시간을 길게 주면 토큰을 무효화 시키기 어렵고, 짧게 주면 재 로그인 해야하는 불편함이 발생한다.
- 따라서 이 문제를 해결하기 위해 JWT의 경우 Access Token, Refresh Token 두가지 토큰을 많이 사용한다.
JWT 사용 시 보안적으로 고려해야 할 사항
Access Token, Refresh Token 이중 토큰 사용
- JWT 관련 문서를 보면 Refesh Token 내용이 많이 있다. 위의 세가지 사항을 잘 처리하기 위해서는 하나의 토큰 만으로는 처리하기 어려운 경우가 많아서 추가적인 Refresh Token 개념이 나오게 되었다.
[Refresh Token이 필요한 이유]
- 서버 세션 기반의 경우 세션 타임 아웃을 30분으로 짧게 해도 사용자는 큰 불편함이 없다. 그 이유는 사용자가 주기적으로 요청을 보낸다면 타임 아웃 시간은 계속 30분으로 연장되기 때문이다.
- JWT의 경우는 유효 시간의 정보가 토큰 자체에 저장되어 있기 때문에 한번 발급된 토큰은 인증 시간을 연장시킬 수 없다. 따라서 JWT에서 타임 아웃 시간을 짧게 설정하면 빈번하게 사용자가 재 로그인 해야하는 불편함이 있고 시간을 길게 하면 토큰 탈취의 보안에 취약해지게 된다.
- 이런 문제를 해결하기 위해 매번 요청 시 인증된 사용자 임을 증명하기 위해 사용되는 Access Token과 Access Token이 만료된 경우 사용자의 재 로그인 없이 Access Token을 재발급 받는데 사용하는 Refresh Token 두가지 종류의 토큰을 사용하게 된다.
- Refresh Token은 Access Token 보다는 훨씬 긴 유효시간을 가지게 설정한다.
- Refresh Token의 유효 시간이 길면 보안에 취약하기 때문에 Access Token을 재발급 할 때에는 보안 관련 사항을 점검한 후 발급해야 한다.
- Refresh Token 발급 시 IP, 브라우저 죵류, 버전, 디바이스 등의 정보를 DB에 저장한다.
- 재발급 요청이 오면 Refresh Token 값을 이용하여 1번에서 저장한 정보를 DB에서 가져온다.
- 재발급 요청시의 클라이언트 정보와 DB에서 조회된 정보가 다른 경우 사용자에게 본인이 맞는지 확인하는 절차를 거친다.
- 토큰 재발급 요청은 사용자 별로 Access Token이 만료되었을 때만 발생하기 때문에 위와 같이 다소 시간이 걸리는 로직을 수행해도 시스템 성능에는 영향이 없다.
- Refresh Token을 사용하게 되면 토큰 탈취를 당했을 때 Refresh Token 관리자가 무효화 처리를 시키면 Access Token 재발급을 강제적으로 막을 수도 있습니다.
토큰 탈취 관련
- 일반적인 상황에서는 토큰 또는 세션의 탈취가 어렵겠지만 해커는 다양한 방법으로 탈취를 시도한다. 그러기 위해서는 대표적으로 XSS(Cross-site scripting)과 CSRF(Cross-Site Request Forgery)에 대한 이해도 필요하다.
- XSS
- XSS 공격을 통해 브라우저 로컬 스토리지나 쿠키 정보를 해커 사이트로 보낼 수 있다.
- 해커는 해당 사이트에서 제공하는 댓글달기, 글쓰기 등의 글을 작성한다.
- 로그인한 사용자가 글을 조회할 경우 세션ID값이 해커 사이트로 전송된다.
- 해커는 이 토큰을 이용하여 사용자로 위장하는 경우가 발생할 수 있다.
- CSRF
- 악성 게시글을 등록하는 것은 동일하나 그 내용이 해커 사이트로 토큰을 탈취하는 것이 아니라 현재 사용중인 사용자가 다른 액션을 처리하게 하는 행위이다.
- 현재 사용자가 로그인된 사이트로 사용자가 의도하지 않은 DELETE, PUT, POST 등의 액션을 보내 주문취소, 자동 주문 등을 실행할 수 있게 된다.

- 브라우저의 저장소 특징을 이용하여 어느 저장소에 어떤 방식으로 Access Token, Refresh Token 을 저장할 것인가 선택해야 한다.
