JWT 는 처음에 설정된 만료 시간을 바꿀 수 없다. 그렇기 때문에 만료시간이 지나, 로그인 시간을 연장하려면 Refresh Token 을 이용하여 새로운 Access Token 을 발급받는 과정을 거쳐야 한다. 그렇다면 로그아웃은 어떻게 구현하는 것이 좋을까?

욜로가 서버에서의 로그아웃

Token 의 만료 시간을 임의로 조작할 수 없기 때문에 사용자로부터 로그아웃된 Token 이 요청을 보낼 경우 로직을 수행하면 안된다. 즉, 매번 요청을 보낼 때마다 JWT 저장 여부를 확인하고 로그아웃된 사용자인지 아닌지를 판단해야 한다는 의미이다. JWT 는 만료 시간을 변경할 수 없기 때문에 특정한 규칙을 만들어서 로그아웃 여부를 판단하는 방식으로 구현한다. 가장 유명한 방식은 Blacklist 방식이다. 요청온 Access Token 이 이전에 로그아웃된 Token 인지 알아보기 위해 Redis 서버에 Access Token 정보도 같이 저장한다.

즉, 사용자가 로그인이 된 상태이면 Refresh Token 만을 저장하고 로그아웃된 상태면 Access Token 만을 저장한다.

Login

"memberId" : {
		accessToken : "",
		refreshToken : "asdf"
}

로그인 요청이 올 경우 accessToken 의 정보를 지우고 refreshToken 을 저장한다.

Logout

"memberId" : {
		accessToken : "asdf",
		refreshToken : ""
}

로그아웃 요청이 올 경우 refreshToken 의 정보를 지우고 accessToken 을 저장한다. 이러한 규칙을 정함으로써 간접적으로 로그아웃을 구현할 수 있다. 로그인 시에 accessToken 도 같이 저장해도 무관하나 accessToken 은 상대적으로 만료 시간이 짧기 때문에 재발급을 받을 가능성이 매우 높다.

Access Token O O X X
Refresh Token O X O X
로그인 여부 로그인 로그아웃 로그인 로그아웃
비고 Access Token 이 만료될 경우

위의 두 가지 규칙외에 발생할 수 있는 모든 경우의 수를 따져보면 다음과 같다. 즉, Refresh Token 의 존재 여부에 따라서 로그인의 여부가 갈린다. 따라서 Blacklist 방식을 조금 더 단순화하여 Refresh Token 만으로 로그인 여부를 판단하였다.

Login

"memberId" : {
		refreshToken : "asdf"
}

Logout

"memberId" : {
		refreshToken : ""
}

OAuth 서버에서의 로그아웃

클라이언트의 JWT 만료 시간이 아직 남아있더라도 욜로가 서버에서 저장하는 JWT 자체를 제거하여 기능을 수행하지 못하도록 막았다. 하지만 클라이언트가 보유하고 있는 JWT 자체가 만료된 것은 아니다. 즉, 클라이언트가 외부 서버에게 직접 기능을 요청하면 원하는 기능이 동작될 가능성이 있다. 이를 방지하기 위해 로그아웃 시 외부 서버에게도 로그아웃 요청을 보내야 한다.