Q> JWT(JSON Web Token) 개발시 Toekn의 생성부터 폐기까지 라이프사이클에 대한 문의

JWT Token방식은 Session방식과 다르게 생성한 JWT를 서버에 저장하지 않는다고 했는데
그렇다면, 서버는 접근이 허용된 클라이언트를 어떻게 식별을 하며, 나중에 Token은 어떻게 폐기를 하나요?

A>

- Session 방식은 서버가 Session을 생성 및 저장하고 클라이언트에게 보냈다가 클라이언트의 요청시 두개의 값을 비교하여 허용된 클라이언트인지를 식별하는 방식이라면,
- JWT Token 방식은 이와 다르게, 인증과정을 거친 후에 클라이언트의 정보를 이용하여 자신의 Private key로 Token을 생성하고 클라이언트에 보낼 뿐 서버가 이를 저장하지 않으며, 클라이언트 요청시 보내온 JWT가 자신의 Private key로 발행한 Token인지를 확인함으로써 허용된 클라이언트인지를 식별하는 방식이다.
- 일반적인 웹 어플리케이션 서비스에서 클라이언트가 로그인하는 단계부터 서버가 클라이언트를 식별되는지 Lifecycle의 관점에서 그 과정을 이해한다면 도움이 될 것 같다.
1. 사용자 로그인 및 JWT토큰 발급

- 사용자가 인증정보(예:아이디, 비밀번호)를 이용하여 웹 애플리케이션에 로그인 요청을 보낸다.
- 서버는 사용자의 인증정보(예:아이디, 비밀번호)를 검증한다.
- 인증에 성공하면, 서버는 로그인된 사용자 정보와 서버의 Private key를 이용하여 JWT를 생성한다.
- 서버는 생성된 JWT토큰을 클라이언트에게 전송한다.

2. 클라이언트에서 JWT 토큰 저장

- 일반적으로 서버는 Blacklisting, 재사용 등과 같은 특별한 목적 이외에는 자신이 발행한 JWT토큰을 별도로 저장하지 않는다.
- 그러나 클라이언트는 서버가 전송한 JWT를 사용해야 하기 때문에 브라우저의 쿠키, 세션스토리지, 로컬스토리지 등 안전한 저장소와 방법으로 JWT를 저장한다.

3. 클라이언트에서 JWT토큰 사용

- 클라이언트는 서버에게 어떤 요청을 보낼때, 자신이 저장하고 있는 JWT를 HTTP헤더에 포함시켜 서버에 전송한다.
- 대부분 “Authorization”, “WWW-Authenticate”헤더 변수에 “Bearer [토큰]” 형태로 전송한다.

4. 서버측에서 JWT 토큰 검증

- 서버는 클라이언트의 요청시 HTTP헤더에 있는 JWT를 검증하는데, 이 과정에서 서버의 Private key로 Signature 부분을 확인하여 자신이 발행한 JWT가 맞는지 검증한다.
- JWT의 Signature 검증결과가 유효하면 Payload부분을 해독하여 클라이언트의 정보를 확인할 수 있다.
- 이렇게 서버는 클라이언트를 식별하고 해당 클라이언트의 권한에 따라 요청을 처리한다.
- 또한, JWT에 설정된 토큰 만료시간 “exp”값 또는 Blacklist 존재 여부를 확인하여 클라이언트가 보낸 JWT토큰의 유효성 여부도 검증을 한다.

5. JWT토큰 만료 및 재발급

- JWT토큰이 만료시기가 도래하면 클라이언트는 “Refresh Token”과 같은 메커니즘을 통해 새로운 JWT를 발급 받을 수 있다.
- 전통적인 Session 처럼 생성부터 폐기까지의 Lifecycle을 생각하면 JWT토큰방식은 서버에 저장하지 않고 클라이언트에 저장하는 방식이기 때문에 서버에서 폐기단계를 구현하는 것이 없다.
- 그러나 이런 기능을 대신하는 것이 “exp”설정과 Token Blacklisting 기능을 구현하는 것이다.
- Blacklisting 기능구현을 위해 Redis와 같은 메모리 데이터베이스를 사용하는 것이 일반적인데, 모든 Token을 생성할 때 마다 Redis에 저장하고 있다가 폐기하는 기능을 구현할 수는 있으나 이 방법은 JWT를 이용하는 목적과는 상반되는 방법이기 때문에 추천하지 않는 방법이다.
- 따라서, “exp”를 이용한 Token만료기간 설정과 Blacklisting 기능을 이용하여 만료되거나 또는 로그아웃 등으로 유효하지 않은 JWT Token이 악의적 사용자에게 악용되지 않도록 해야 한다.