인터넷에 리액트로 OAuth를 구현하는 방법에 대해 쳐보면 첫번째 그림 같은 코드가 대부분이다. 즉, 대다수의 예제가 클라이언트 쪽에서 OAuth의 provider에게 요청을 보내고 그 응답 결과를 다시 백엔드 쪽에 보내고 이에 대한 응답을 받음으로써 인증 절차를 처리한다. 우리 서비스는 훌륭한 백엔드 팀원이 OAuth provider와의 통신을 처리해놓았기 때문에 클라이언트 쪽에서 로그인이나 인증 요청만 보내면 jwt 토큰을 전달받을 수 있다.
현재 위 인증 과정이 구현된지 몇 달이 지났기 때문에 처음 기능을 구현하고 로그인했던 계정에서 만료된 토큰 오류가 발생했다. 현재 가장 쉽게 이 오류를 방지할 수 있는 방법은 서비스에 protected routing이 적용되어 있으므로, 인증이 필요한 페이지에 접속하기 전 토큰이 만료되었는지를 확인하는 것이다. 처음엔 '다담다' 프로젝트는 위처럼 구현되어 있으므로, 토큰이 만료되었는지를 백엔드쪽에서 알려주어야 한다고 생각했다. 하지만, 프론트엔드쪽에서 jwt자체를 decoding하면 만료 시간을 알 수 있어 더 간단하게 해결할 수 있다.
인터넷에 리액트로 jwt를 decoding하는 방법에 대해 검색하면 대다수의 예제가 json web token
라이브러리의 verify함수를 통해 유효한 토큰인지를 검증하던데, 해당 라이브러리 자체를 설치하고 실행하는 데에 오류가 꽤 있었다.
분명히 설치했는데 해당 모듈을 찾지 못하는 오류가 발생하여 찾아보니
나와 같이 해당 라이브러리가 동작하지 않는다는 후기들을 심심치 않게 찾아볼 수 있었다. 결국, 이 라이브러리를 사용하지 않고 해결하는 방법을 찾아보기로 하였다.
우선, 실제 토큰이 만료되면 적용해놓은 코드가 동작하는지 알기 위해서 토큰 만료 시간 설정을 변경해야 한다. yml 파일에서 security.jwt.token
의 expire-length을 아주 짧게 변경한다.
# 스프링 시큐리티 설정
security.jwt.token:
secret-key: 비밀
expire-length : 10
function verifyToken(token: string | null) {
if (!token) {
return false;
}
const tokenData = JSON.parse(atob(token.split('.')[1]));
if (tokenData.exp) {
const expirationDate = new Date(tokenData.exp * 1000);
const currentDate = new Date();
return expirationDate > currentDate;
}
return false;
}
이 verifyToken 함수는 토큰의 만료 기간이 더 남아 있어야 즉, 유효한 토큰이어야지 true
가 반환되고 이외의 경우(토큰이 없는 경우도 포함)에는 false
를 반환한다.
!verifyToken(token) && useHandleUnVerifiedTokenUser();
useHandleUnVerifiedTokenUser 함수는 만료된 토큰일 때 어떻게 처리할지를 정의해놓은 함수로 유저를 로그아웃 시키고, 토스트를 통해 다시 로그인하라는 알림을 띄워준다.
이제는 서비스에 성공적으로 만료된 토큰 에러 처리를 추가하였다. (서비스에서 확인해보시려면... 다담다 서비스 바로가기)
자주 있는 경우는 아니겠지만, 사용자가 라우팅에 들어왔을 때에는 만료되지 않은 토큰이었다가 요청을 날리는 시점에는 토큰이 만료되어버리는 경우가 있을 수 있다. 따라서, 각 요청에도 토큰 만료에 대한 오류 처리를 추가해야할 것 같다.