. NET Core Angular клиентское SPA имеет проблему с перенаправлением при выходе из системы в IdentityServer4 IDP - PullRequest
0 голосов
/ 18 января 2020

У меня есть Angular Клиент, который должен быть аутентифицирован. Этот клиент находится в .NetCore SPA. Теперь, используя IdentityServer4, я настроил IDP для аутентификации Клиента.

Все отлично работает для входа в систему. Здесь клиент автоматически перенаправляет в проект IDP для входа в систему. После ввода учетных данных оно будет перенаправлено обратно в клиентское приложение.

Однако для выхода из системы это не работает. На клиенте Angular, который размещен как SPA в .netcore, у меня есть кнопка выхода из системы. Это событие кнопки выхода из системы вызовет контроллер API в том же клиенте. В этом контроллере есть код для выхода из httpContext.

Я ожидал, что когда в контроллере будет вызвано действие выхода из системы, оно выйдет из системы и перенаправит меня обратно в IDP. Положительным моментом является то, что я реализовал то же самое в MVC клиенте (без SPA и angular), и он работает для выхода из системы, перенаправив меня обратно в IDP.

Также еще один положительный момент на angular клиент при выходе из системы фактически пытается выйти из системы, но политика CORS блокирует его . Сообщение об ошибке в консоли браузера содержит URL-адрес перенаправления как часть сообщения об ошибке. Этот URL работает, когда я нажимаю на него, перенаправляя меня в IDP и выполняя выход из системы.

Я не могу выяснить, какую политику CORS я должен добавить, чтобы эта работа перенаправления работала. Я пытался добавить CORS в класс запуска, но не получилось. Помогите пожалуйста

Сообщение об ошибке браузера:

Доступ к XMLHttpRequest по адресу https://localhost: 44336 / connect / endsession? Post_logout_redirect_uri = https% 3A % 2F% 2Flocalhost% 3A44374% 2Fsignout обратный вызов-РСИН & id_token_hint = eyJhbGciOiJSUzI1NiIsImtpZCI6IlMwbFpqUi1QazItS0dLc2xxaFlQQ2ciLCJ0eXAiOiJKV1QifQ..bd35dk-lcolUxgoNAzzc4kKIORQIsmeSu5JaARpyqj1I6cv5P6LSHrcdw3YmZ80q_tF8WLi7ywIml-enEP4JAe-nbYw7gSlFt9qHtw5eSF37dMdBZq7UUXt6EoK29xs9lp6TyIB11pzgRZ8tPVAPw0Y8rNpGSGYtjfWjp7t4FdKthvUchAo_SNh6l40S5oV0Yo_YIWfHtjxM-nLZXia0YCvjNEQChmTmkzSMCIdGnVqawhIzQ_O7jv0c1T7kCwaF5YGyer3ZUyj1UM53JTBbbGpKDrDh2DV-kd4tvhoaLnWQAoUqCQ1Ofl_kHc8vffqE7RRPGmQLQYOM48186hIe0g & состояние = CfDJ8DRPXADjz9hKioMAFvg6DCP1P37ODZ4R81EV3uFXBpxiOLWoJY6GDEcbYNZzB - zZjv-Z94PSfMJkcoJhQcmHAvmM_9yKL9hPaGqmucpJrO_wv74Fj8bmdm8C7l_MJZ3VaNahF5Bqvi9tWFUikbr-HJ_uI0GiGX6qsj5mkrp8K4x & х-клиент-ы = ID_NETSTANDARD2_0 & х-клиент-вер = 5.5.0.0 '(перенаправлено из' https://localhost: 44374 / api / Авторизация / Выход из системы ') из источника' https://localhost: 44374 'заблокировано политикой CORS: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin»

и код выхода из контроллера API:

    [HttpGet]
    public async Task Logout()
    {
        var httpclient = new HttpClient();
        var disco = await httpclient.GetDiscoveryDocumentAsync("https://localhost:44336/");

        // get the access token to revoke 
        var accessToken = await HttpContext
          .GetTokenAsync(OpenIdConnectParameterNames.AccessToken);

        if (!string.IsNullOrWhiteSpace(accessToken))
        {
            var revokeAccessTokenResponse =
                await httpclient.RevokeTokenAsync(new TokenRevocationRequest
                {
                    Address = disco.RevocationEndpoint,
                    ClientId = "App_ClientId",
                    ClientSecret = "someSecret",

                    Token = accessToken
                });

            if (revokeAccessTokenResponse.IsError)
            {
                throw new Exception("Problem encountered while revoking the access token."
                    , revokeAccessTokenResponse.Exception);
            }
        }

        // Clears the  local cookie ("Cookies" must match name from scheme)
        await HttpContext.SignOutAsync("Cookies");
        await HttpContext.SignOutAsync("oidc");
    }

Startup.cs со всей конфигурацией клиента

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddScoped<ActivityTrackerAPIHttpClient>();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        }).AddCookie("Cookies")
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = "Cookies";
            options.Authority = Configuration["IdentityServer:Authority"];
            options.ClientId = Configuration["IdentityServer:ClientId"];
            options.ClientSecret = Configuration["IdentityServer:ClientSecret"];
            options.ResponseType = "code id_token";
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("roles");
            options.Scope.Add(Configuration["IdentityServer:ApiName"]);
            options.Scope.Add("offline_access");
            options.SaveTokens = true;
            options.GetClaimsFromUserInfoEndpoint = true;
            options.ClaimActions.Remove("amr");
            options.ClaimActions.DeleteClaim("sid");
            options.ClaimActions.DeleteClaim("idp");
            options.ClaimActions.MapJsonKey("role", "role");

            options.TokenValidationParameters = new TokenValidationParameters
            {
                RoleClaimType = JwtClaimTypes.Role,
            };
        });

        services.ConfigureLoggerService();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseAuthentication();

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        if (!env.IsDevelopment())
        {
            app.UseSpaStaticFiles();
        }

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
        });

        app.Use(async (context, next) =>
        {
            if (!context.User.Identity.IsAuthenticated)
            {
                await context.ChallengeAsync("oidc");
            }
            else
            {
                await next();
            }
        });

        app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...