ASP. NET Веб-сайт Core 3.1 и удаленный API с IdentityServer4 в качестве IDP, как обновить sh access_token - PullRequest
0 голосов
/ 21 февраля 2020

Я создаю ASP. NET Core 3.1 серверное веб-приложение Blazor для клиентского компонента, отдельный ASP. NET Core 3.1 API для серверной службы данных и отдельный ASP . NET Реализация IdentyServer4 на основе Core 3.1 в качестве поставщика услуг идентификации.

Все работает, как я ожидаю, за исключением следующего:

После того, как пользователь вошел в систему и получил доступ к данным из API, через некоторое время веб-клиент больше не может получить доступ к API потому что я получаю 401 обратно от вызова API, указывающего, что срок действия маркера доступа истек. Пользователь все еще вошел в систему, и веб-приложение, похоже, автоматически обновляет токен oid c, но для API истекает срок действия access_token.

Я просматривал некоторые сообщения SO, в которых говорится о проверить дату истечения срока действия токена доступа и, если он истек, получить новый access_token от провайдера ID. Но примеры кода для более старых версий ASP. NET Core и использования angular для клиента, а не на стороне сервера Blazor.

Итак, сначала я хочу подтвердить, что не существует встроенного метода для автоматического обновления access_token после истечения срока действия. Если нет, то каков будет лучший способ продления просроченного access_token в моем сценарии.

В этом SO post говорится о процессе проверки значения "expires_at" в токене и, если оно истекло по сравнению с текущим DateTime, вызовите новый access_token. Но пример кода основан на клиенте MVC / Ajax. Я пытаюсь выяснить, есть ли что-нибудь встроенное в ASP. NET Core 3.1 с серверной Blazor, которое я могу использовать для процесса обновления токена доступа. Если нет, может ли кто-нибудь предоставить текущий лучший пример того, как обновить маркер доступа?

В IdentityServer4, Config.cs, для веб-клиента, у меня есть следующее в методе stati c IEnumerable Clients ;

new Client
{
    ClientId = "myweb",
    ClientName = "Client for My Web",
    AllowedGrantTypes = GrantTypes.Hybrid, 
    ClientSecrets = { new Secret("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".Sha256()) },
    RedirectUris = { "https://mysite/signin-oidc" }, 
    PostLogoutRedirectUris = { "https://mysite/signout-callback-oidc" },
    AllowOfflineAccess = true,
    RequireConsent = false,
    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        IdentityServerConstants.StandardScopes.OfflineAccess,
        IdentityServerConstants.StandardScopes.Email,
        "myapi"
    } 
}

и для клиента API у меня есть следующее:

new Client
{
    ClientId = "myapi",
    ClientName = "Client for MyAPI",
    AllowedGrantTypes = GrantTypes.ClientCredentials,
    AllowAccessTokensViaBrowser =true,
    RequireConsent = false,
    RedirectUris = { "https:myapi" },
    PostLogoutRedirectUris = { "https://www.getpostman.com" },
    AllowedCorsOrigins = {"https://www.getpostman.com"},
    EnableLocalLogin = true,
    AllowedScopes = { "myapi", "country" },
    ClientSecrets = 
    { 
        new Secret("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".Sha256()) 
    },
}

А вот моя конфигурация службы IdentityServer в методе Startup.cs -> ConfigureServices.

var builder = services.AddIdentityServer(options =>
{
    options.Events.RaiseErrorEvents = true;
    options.Events.RaiseInformationEvents = true;
    options.Events.RaiseFailureEvents = true;
    options.Events.RaiseSuccessEvents = true;
    options.Authentication.CookieSlidingExpiration = true;

}).AddAspNetIdentity<ApplicationUser>();

В клиентском приложении Blazor на стороне сервера ASP. NET Core 3.1 у меня есть следующий код в службе:

public async Task<ODataProductsResponse> GetProducts(DataSourceRequest request, CancellationToken cancellationToken)
{
    try
    {
        var baseUrl = $"{_utilities.GetBaseApiUrl()}/products?";
        var requestUrl = $"{baseUrl}{request.ToODataString()}";
        var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);
        var client = _httpClientFactory.CreateClient("MyApi");
        var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        if (accessToken != null)
        {
            client.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
        }
        var response = await client.SendAsync(requestMessage, cancellationToken);
        if (response.IsSuccessStatusCode)
        {
            var body = await response.Content.ReadAsStringAsync();
            var oDataResponse = JsonSerializer.Deserialize<ODataProductsResponse>(body);
            return oDataResponse;
        }
        throw new HttpRequestException("Request failed.");
        //TODO: Parse error object and return to display error as an alert.
    }
    catch (Exception ex)
    {
        const string message =
            "An exception has occurred while trying to get a list of Products from the API.";
        _logger.LogError(ex, message);
        throw;
        //TODO: Add error object to result. Display to user as a HttpStatus 500 
    }
}

А вот моя конфигурация службы в Startup.cs -> метод ConfigureServices моего ASP. NET Core 3.1 веб-приложения.

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme,
    options =>
    {
        options.Authority = Configuration["IdentityProviderSettings:Authority"];
        options.ClientId = Configuration["IdentityProviderSettings:ClientId"];
        options.ClientSecret = Configuration["IdentityProviderSettings:ClientSecret"];
        options.ResponseType = Configuration["IdentityProviderSettings:ResponseType"];
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("email");
        options.Scope.Add("myapi");
        options.Scope.Add("offline_access");
        //options.CallbackPath = ...
        options.SaveTokens = true;
        options.GetClaimsFromUserInfoEndpoint = true;
    });

Итак, я ищу пример кода, как наилучшим образом определить, что access_token имеет истек срок действия и, если да, то как запросить новый access_token, учитывая тот факт, что начальный access_token был получен как часть потока GrantTypes.Hybrid из IdentityServer4 (если это действительно имеет значение).

Или, если есть лучший способ продлить (или автоматически продлить?) Access_token в этом ASP. NET Core 3.1x сценарии.

Есть идеи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...