@dotnetcsharp

Как правильно обновить JWT токен перед HTTP запросом?

Добрый день, у меня в проекте JWT аутентификация. Я хочу правильно научиться работать с обновлением токена. Не могу корректно создать архитектуру. Суть в том, что бы обновлять JWT токен перед отправкой HTTP запроса к API.
У меня есть код на получение списка пользователей в UserService
public class UserService : IUserRepository
{
    public UserService() {
    }
    public async Task<List<ExchangesViewModel>> GetExchanges()
    {
        return await new HttpClient().GetFromJsonAsync<List<ExchangesViewModel>>("https://ip:5007/api/Crypto/GetExchanges");
    }
    public async Task<AuthenticatedResponse> Login(SU_001LoginViewModel sU_001LoginViewModel)
    {
        var options = new RestClientOptions("https://ip:5007")
        {
            MaxTimeout = -1,
        };
        var client = new RestClient(options);
        var request = new RestRequest("/api/User/Login", Method.Post);
        request.AddParameter("application/json", JsonSerializer.Serialize(sU_001LoginViewModel), ParameterType.RequestBody);
        var r = client.ExecuteAsync(request).Result.Content;
        var userd = JsonSerializer.Deserialize<AuthenticatedResponse>(r);
        return userd;
    }
    public async Task<AuthenticatedResponse> Refresh(AuthenticatedResponse sU_001LoginViewModel)
    {
        var options = new RestClientOptions("https://ip:5007")
        {
            MaxTimeout = -1,
        };
        var client = new RestClient(options);
        var request = new RestRequest("/api/User/Refresh", Method.Post);
        request.AddParameter("application/json", JsonSerializer.Serialize(sU_001LoginViewModel), ParameterType.RequestBody);
        var r = client.ExecuteAsync(request).Result.Content;
        var userd = JsonSerializer.Deserialize<AuthenticatedResponse>(r);
        return userd;
    }

    public async Task<List<SU_001ListViewModel>> GetUsers(string token)
    {
        try
        {
            var options = new RestClientOptions("https://ip:5007")
            {
                MaxTimeout = -1,
            };
            var client = new RestClient(options);
            var request = new RestRequest("/api/User/GetUsers", Method.Get);
            //request.AddParameter("application/json", token, ParameterType.RequestBody);
            request.AddParameter("token", token);
            var r = client.ExecuteAsync(request).Result.Content;
            var userd = JsonSerializer.Deserialize<List<SU_001ListViewModel>>(r);
            return userd;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            return new List<SU_001ListViewModel> { };
        }
    }
}


В представлении есть следующий код:
var AccessToken = await ProtectedLocalStore.GetAsync<string>("AccessToken");
var RefreshToken = await ProtectedLocalStore.GetAsync<string>("RefreshToken");
var result = await ProtectedLocalStore.GetAsync<string>("AccessToken");
if (result.Value != null)
{
    AuthenticatedResponse aresp = new AuthenticatedResponse();
    aresp.AccessToken = AccessToken.Value;
    aresp.RefreshToken = RefreshToken.Value;
    Console.WriteLine("old token");
    Console.WriteLine(aresp.AccessToken);
    
    AuthenticatedResponse a = await UserRepository.Refresh(aresp);

    Console.WriteLine("New token");
    Console.WriteLine(a.AccessToken);
    await ProtectedLocalStore.SetAsync("RefreshToken", a.RefreshToken!);
    await ProtectedLocalStore.SetAsync("AccessToken", a.AccessToken!);
    if (a.AccessToken != null)
    {
        exchanges = await UserRepository.GetUsers(a.AccessToken!.ToString());
    }
    Console.WriteLine(exchanges.First().FirstName);
    StateHasChanged();
}


Все работает, код
await UserRepository.GetUsers(a.AccessToken!.ToString());

у меня выполняется только после того как я в localstorage обновлю accesstoken и его передам в запрос. Но я думаю что это не лучший вариант мне на каждом представлении писать такой код. Есть вариант как-нибудь по-нормальному обновить токен в localstorage и уже обновленный токен отправлять в запрос?

Я пробовал реализовать способ обновления токена при входе на сайт, но из-за того что запросы асинхронные иногда выпадает так что запрос списка пользователей срабатывает быстрее чем пока придет ответ с данными по новому токену.
  • Вопрос задан
  • 248 просмотров
Решения вопроса 1
@OwDafuq
Имхо, но обновлять JWT перед каждым запросом - не хорошо. У токенов есть время жизни, если оно подходит к концу или уже кончилось - обновляйте.
У себя я решил это через interceptor для HttpClient'a, который проверяет токен на время жизни и сам его автоматически обновляет, вам нужно думать в эту сторону тоже. Руками это делать как-то не комильфо.

Так делать не стоит:
return await new HttpClient().GetFromJsonAsync

Зачем вам асинхронный метод, когда вы целенаправленно пишите код так:
var r = client.ExecuteAsync(request).Result.Content;


Каким образом получение токена у вас может завершиться после получения списка пользователей - тоже загадка.

Почему-то названия для ЗАПРОСА называется как AuthenticatedResponse, а не AuthenticatedRequest (например).

Все работает
- ок, а вопрос тогда в чем?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы