При авторизации выдаются сразу оба токена, рабочий и refresh. Refresh-токен сохраняется в базе сервера вместе с идентификатором пользователя, рабочий токен хранить смысла нет.
Срок жизни записан в самом токене, как одно из полей полезной нагрузки (payload). Прочитать это поле может и сервер и клиент. Сервер в любом случае должен контролировать срок жизни токена, клиент может это делать сам, а может просто реагировать на ответы сервера.
Каждый запрос к серверу сопровождается рабочим токеном. Если срок жизни рабочего токена истёк, то сервер возвращает сообщение о необходимости обновления токена.
Запрос на обновление сопровождается refresh-токеном.
Если refresh-токен в базе помечен как уже использованный, то инактивируются (удаляются из базы) все refresh-токены данного пользователя и возвращается сообщение о необходимости повторной авторизации.
Refresh-токен отмечается в базе как использованный .
Если срок действия refresh-токена истёк или такого refresh-токена нет в базе сервера, то возвращается сообщение о необходимости повторной авторизации.
Возвращается новая пара токенов.
Где и как хранить токены на клиенте - вопрос предпочтений. Можно не хранить вообще, тогда при перезагрузке страницы пользователю придётся авторизоваться заново. Можно сохранять только refresh-токен, выполняя запрос на обновление при запуске приложения / открытии страницы.