简体   繁体   English

IdentityServer4 + ASP.Net Core Identity 从客户端注销不会在 ID4 上注销

[英]IdentityServer4 + ASP.Net Core Identity Signout from Client does not logout on ID4

I have I am using ID4 for OIDC and ASP.Net Core Identity to manage the user membership.我使用 ID4 作为 OIDC 和 ASP.Net Core Identity 来管理用户成员资格。 Razor with Pagemodel.带有 Pagemodel 的剃刀。 I have a test client that properly logs in with SSO.我有一个使用 SSO 正确登录的测试客户端。 On logout , it log outs of the client OK, but does not logout from the ID4 server.在注销时,它会注销客户端,但不会从 ID4 服务器注销。

On Logout, the client redirects to my ID4 server using the end session url.在注销时,客户端使用结束会话 url 重定向到我的 ID4 服务器。 It does have hint token.它确实有提示令牌。 The ID4 server does show the logout page, but it still is logged in. I suspect the problem is that I am using scafolded ASP.Net Identity pages for login/logout. ID4 服务器确实显示了注销页面,但它仍处于登录状态。我怀疑问题是我使用脚架式 ASP.Net Identity 页面进行登录/注销。

Manually clicking on the logout button on the ID4 server works as expected.手动单击 ID4 服务器上的注销按钮按预期工作。 The user is logged on on the server and on the client.用户登录到服务器和客户端。

I am able to get it to work by redirecting to the ASP.Net Core Indentity logout page and have the OnGet method call _signInManager.SignOutAsync().我可以通过重定向到 ASP.Net Core Indentity 注销页面并让 OnGet 方法调用 _signInManager.SignOutAsync() 来使其工作。 But this seems like a poor solution to me.但这对我来说似乎是一个糟糕的解决方案。

Reading the ID4 docs, spec and many github and SO posts, I have the following logout code on my client:阅读 ID4 文档、规范以及许多 github 和 SO 帖子,我的客户端上有以下注销代码:

var id_token = (await HttpContext.AuthenticateAsync()).Properties.Items[".Token.id_token"];

await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");

var redirectUrl = $"{Startup.IdentityServerUrl}/connect/endsession?id_token_hint={id_token}";

return Redirect(redirectUrl);

And here is the startup code for my client:这是我的客户的启动代码:

  // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
            options.DefaultChallengeScheme = "oidc";
        })
            .AddCookie("Cookies")
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = IdentityServerUrl;
                options.RequireHttpsMetadata = false;

                options.ClientId = "testClient1";
                options.ClientSecret = "xxxxxxxxxxxxx";
                options.ResponseType = "code";

                options.SaveTokens = true;
            });


        services.AddRazorPages();


    }

    // 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.UseStaticFiles();

        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapDefaultControllerRoute()
                .RequireAuthorization();
        });

    }

Here is the startup code for my ID4 server:这是我的 ID4 服务器的启动代码:

 public void ConfigureServices(IServiceCollection services)
    {
        var connectionString = Configuration.GetConnectionString("DefaultConnection");

        var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(connectionString));

        services.AddIdentity<ApplicationUser, IdentityRole>(
           config =>
           {
               config.SignIn.RequireConfirmedEmail = true;
               config.SignIn.RequireConfirmedAccount = true;
               config.User.RequireUniqueEmail = true;
               config.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
               config.Lockout.MaxFailedAccessAttempts = 5;
               config.Lockout.AllowedForNewUsers = true;
           })
               .AddEntityFrameworkStores<ApplicationDbContext>()
               .AddDefaultTokenProviders();



        // these point ID4 to the correct pages for login, logout, etc.
        services.ConfigureApplicationCookie((options) =>
        {
            options.LoginPath = "/Identity/Account/Login";
            options.LogoutPath = "/Identity/Account/Logout";
            options.AccessDeniedPath = "/Error";
        });


        services.AddIdentityServer()
            .AddOperationalStore(options =>
                options.ConfigureDbContext = builder =>
                    builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
            .AddConfigurationStore(options =>
                options.ConfigureDbContext = builder =>
                    builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
            .AddAspNetIdentity<ApplicationUser>()
            .AddDeveloperSigningCredential();

        ConfigureEmailServices(services);

        services.AddRazorPages();


    }

    // 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();
            app.UseDatabaseErrorPage();

            InitializeDbTestData(app);

        }
        else
        {
            app.UseExceptionHandler("/Home/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.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseIdentityServer();

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

            endpoints.MapRazorPages();
        });
    }

For the idp logout you don't need to redirect manually.对于 idp 注销,您不需要手动重定向。 Simply return a SignOutResult and the redirection will be done by the oidc handler by using discovery endpoint and mounting the request properly.简单地返回一个SignOutResult ,重定向将由 oidc 处理程序通过使用发现端点并正确安装请求来完成。 Put this code in your logout method:将此代码放在您的注销方法中:

 return SignOut(new[] { "Cookies", "oidc" });

Or this other:或者这个其他:

return new SignOutResult(new[] { "Cookies", "oidc" });

If you want to be redirected to the client after the idp logout, set up your postLogoutRedirectUri.如果您想在 idp 注销后重定向到客户端,请设置您的 postLogoutRedirectUri。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM