Ответ 1
Прежде всего, вам нужно сгенерировать токен обновления и сохранить его где-нибудь. Это потому, что вы хотите иметь возможность сделать его недействительным, если это необходимо. Если вы должны следовать тому же шаблону, что и токен доступа - где все данные содержатся в токене - токен, который попадает в чужие руки, может быть использован для генерации новых токенов доступа на весь срок действия токена обновления, который может быть очень долго
Так какого черта ты должен сохраняться?
Вам нужен какой-то уникальный идентификатор, который не легко угадать, GUID подойдет просто отлично. Вам также нужны данные, чтобы иметь возможность выдать новый токен доступа, скорее всего, имя пользователя. Имея имя пользователя, вы можете пропустить VerifyHashedPassword (...) -part, но в остальном просто следуйте той же логике.
Чтобы получить токен обновления, вы обычно используете область "offline_access", которую вы предоставляете в своей модели (CredentialViewModel) при выполнении запроса токена. В отличие от обычного запроса токена доступа, вам не нужно указывать имя пользователя и пароль, а вместо этого токен обновления. При получении запроса с токеном обновления вы просматриваете постоянный идентификатор и выдает токен для найденного пользователя.
Ниже приведен псевдокод для счастливого пути:
[Route("Token")]
[HttpPost]
public async Task<IActionResult> CreateToken([FromBody] CredentialViewModel model)
{
if (model.GrantType is "refresh_token")
{
// Lookup which user is tied to model.RefreshToken
// Generate access token from the username (no password check required)
// Return the token (access + expiration)
}
else if (model.GrantType is "password")
{
if (model.Scopes contains "offline_access")
{
// Generate access token
// Generate refresh token (random GUID + model.username)
// Persist refresh token
// Return the complete token (access + refresh + expiration)
}
else
{
// Generate access token
// Return the token (access + expiration)
}
}
}