Blazor (на стороне сервера) с IdentityServer4

Я пытаюсь заставить IdentityServer4 (с локальным API) работать с интерфейсом Blazor (на стороне сервера).

Мне удалось создать серверную часть IdentityServer. Функции входа в систему работают, и он проходит проверку подлинности с помощью настройки удостоверения ASP.NET на бэкэнде. После аутентификации я могу (используя Postman) взять токен на предъявителя и вызвать API, чтобы получить успешные результаты.

Я хочу знать, понял ли кто, как:

  1. Автоматическое перенаправление Blazor (на стороне сервера) при переходе на страницу, требующую авторизации
  2. Как только пользователь успешно входит в IdentityServer, как передать эту информацию в context.User приложения Blazor. Если это вообще возможно, я могу ошибиться в терминологии.

Я надеюсь, что в конечном итоге будет принято не просто использование odic-client.js для выполнения этих вызовов. Даже если это результат, можно ли было бы взять эту информацию обратно из IdentityServer и засунуть ее в context.User?

ОБНОВИТЬ:

Мне удалось связать веб-сайт Blazor с прямым доступом к IdentityServer (а не автонадресу, который нужен в №1), чтобы проверить функциональность.

ReturnUrl перенаправляет с IdentityServer (после успешного входа). Также похоже, что он записывает файл cookie AspNetCore.Identity.Application в файлы cookie веб-сайта Blazor.

Есть ли способ получить эту информацию из файла cookie (если он содержит токены пользователя и носителя)?

ОБНОВИТЬ:

Я обнаружил, что похоже, что код Blazor пытается прочитать файл cookie, но я не знаю, как это проверить. Я получаю это на выходе:

Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.Application signed in.
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (1ms) [Parameters=[@__normalizedUserName_0='?' (Size = 256)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u].[Email], [u].[EmailConfirmed], [u].[LockoutEnabled], [u].[LockoutEnd], [u].[NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled], [u].[UserName]
FROM [AspNetUsers] AS [u]
WHERE [u].[NormalizedUserName] = @__normalizedUserName_0
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method IdentityServer4.Quickstart.UI.AccountController.Login (BQM.API), returned result Microsoft.AspNetCore.Mvc.RedirectResult in 651.558ms.
Microsoft.AspNetCore.Mvc.Infrastructure.RedirectResultExecutor:Information: Executing RedirectResult, redirecting to https://localhost:44370/.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action IdentityServer4.Quickstart.UI.AccountController.Login (BQM.API) in 777.6252ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'IdentityServer4.Quickstart.UI.AccountController.Login (BQM.API)'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 890.8492ms 302 
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/1.1 GET https://localhost:44370/  
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint '/_Host'
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker: Information: Route matched with {page = "/_Host", area = ""}. Executing page /_Host
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker: Information: Executing an implicit handler method - ModelState is Valid
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker: Information: Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService: Information: Authorization failed.
Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker: Information: Executed page /_Host in 16.8805ms

person Rabbitslayer    schedule 16.07.2019    source источник
comment
Это было решено с помощью следующего сообщения: stackoverflow.com/questions/57172840/   -  person Rabbitslayer    schedule 24.07.2019


Ответы (1)


Надеюсь, это поможет тебе.

Мне нужен токен, потому что я хочу вызвать API, защищенный этим токеном. Вы должны добавить вещь в Startup.cs и, чтобы получить ее позже, вы можете посмотреть на класс ниже Startup.cs

Вот что нужно в Startup.cs (важная часть - HttpContextAccessor).

Вам понадобится следующее, используя i Startup.cs

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;

А затем (все еще в Startup.cs):

public void ConfigureServices(IServiceCollection services)
    {

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = 
CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = 
OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect(options =>
        {
            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.Authority = "https://localhost:5001/";
            options.ClientId = "AuthCodeClient";
            options.ClientSecret = "verrystrongpwd";
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.SaveTokens = true;
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("user.management.api");
            options.Scope.Add("identity-provider.Api");
            options.CallbackPath = "/signin-oidc";
        });

        services.AddControllersWithViews(options =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
        });

        services.AddRazorPages();
        services.AddServerSideBlazor();

        // HttpContextAccessor
        services.AddHttpContextAccessor();
        services.AddScoped<HttpContextAccessor>();

........ maybe more code....

Это класс, в котором я получаю информацию из HttpContext как access_token.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Management.Ui.Services
{
  public class TokenContainer
  {
    private readonly IHttpContextAccessor _httpContextAccessor;

    public TokenContainer(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected async Task AddRequestHeaders(HttpClient httpClient)
    {
        var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        httpClient.DefaultRequestHeaders.Accept.Add(
        new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    }
  }
}
person snerting    schedule 22.08.2019
comment
Почему вы добавляете службу HttpContextAccessor дважды? services.AddHttpContextAccessor(); services.AddScoped<HttpContextAccessor>(); - person Edoardo; 01.06.2020