Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 带有IdentityServer4的无止境循环重定向_Asp.net_.net_Authentication_Identityserver4_Openid Connect - Fatal编程技术网

Asp.net 带有IdentityServer4的无止境循环重定向

Asp.net 带有IdentityServer4的无止境循环重定向,asp.net,.net,authentication,identityserver4,openid-connect,Asp.net,.net,Authentication,Identityserver4,Openid Connect,我正在使用FinBulk.Multitenant和IdentityServer4开发多租户ASP.NET MVC应用程序(使用教程中的标准类和控制器)。我的应用程序为租户使用路由策略()并且我为每个租户使用单独的cookie(cookie名为auth.tenant1、auth.tenant2…等等)。除非我为auth cookie指定自定义路径,否则一切都正常。如果它们都有Path=/一切正常。但是,当我将Path=/tenant1设置为名为auth.tenant1的cookie,并为每个其他租

我正在使用FinBulk.Multitenant和IdentityServer4开发多租户ASP.NET MVC应用程序(使用教程中的标准类和控制器)。我的应用程序为租户使用路由策略()并且我为每个租户使用单独的cookie(cookie名为auth.tenant1、auth.tenant2…等等)。除非我为auth cookie指定自定义路径,否则一切都正常。如果它们都有Path=/一切正常。但是,当我将Path=/tenant1设置为名为auth.tenant1的cookie,并为每个其他租户设置相同的模式时,在通过同意屏幕后,我有一个循环重定向。当我在同意屏幕上单击“是”时,我从客户端的IdentityServer中间件获得302质询重定向。它将我重定向回同意屏幕。每次“是”之后,我都会回到同意状态。但是,它仅在身份验证过程中发生。如果我打开新标签并前往,我将不会被重定向,并将成功通过身份验证。 谷歌搜索了好几天的答案,但没有找到任何解决方案。请帮帮我

这是我客户的启动。cs

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services.AddMultiTenant().WithInMemoryStore(Configuration.GetSection("MultiTenant:InMemoryStore"))
            .WithRouteStrategy(MapRoutes)
            .WithRemoteAuthentication()
            .WithPerTenantOptions<AuthenticationOptions>((options, tenantContext) =>
            {
                // Allow each tenant to have a different default challenge scheme.
                if (tenantContext.Items.TryGetValue("ChallengeScheme", out object challengeScheme))
                {
                    options.DefaultChallengeScheme = (string)challengeScheme;
                }
            })
            .WithPerTenantOptions<CookieAuthenticationOptions>((options, tenantContext) =>
            {
                options.Cookie.Name += tenantContext.Identifier;
                options.Cookie.Path = "/" + tenantContext.Identifier;
                options.LoginPath = "/" + tenantContext.Identifier + "/Home/Login";
            });

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
            {
                o.Cookie.Name = "auth.";
            })
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.Authority = "https://localhost:5000";
            options.RequireHttpsMetadata = true;

            options.ClientId = "mvc";
            options.SaveTokens = true;

            options.ClientSecret = "secret";
            //Hybrid protocols (OpenId + OAuth)
            options.ResponseType = OpenIdConnectResponseType.CodeIdToken;

            options.GetClaimsFromUserInfoEndpoint = true;
            //ask to allow access to testApi
            options.Scope.Add("testApi");
            //allows requesting refresh tokens for long lived API access
            options.Scope.Add("offline_access");

            options.Events = new OpenIdConnectEvents()
            {
                OnRedirectToIdentityProvider = ctx =>
                {
                    var tenant = ctx.HttpContext.GetMultiTenantContext()?.TenantInfo?.Identifier;
                    ctx.ProtocolMessage.AcrValues = $"tenant:{tenant}";
                    return Task.FromResult(0);
                }
            };
        });
    }

    private void MapRoutes(IRouteBuilder router)
    {
        router.MapRoute("Default", "{__tenant__=tenant1}/{controller=Home}/{action=Index}/{id?}");
    }
我的IdentityServer4配置:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        var identityServerBuilder = services.AddIdentityServer()
            .AddDeveloperSigningCredential();

        if (_config.GetSection("AppSettings:UseDummyAuthentication").Get<bool>())
        {
            identityServerBuilder
                .AddInMemoryIdentityResources(_config.GetSection("IdentityResources"))
                .AddInMemoryApiResources(_config.GetSection("ApiResources"))
                .AddInMemoryClients(_config.GetSection("Clients"))
                .AddTestUsers(_config.GetSection("TestUsers"));
        }

        services.AddAuthentication();
    }
public void配置服务(IServiceCollection服务)
{
services.AddMvc();
var identityServerBuilder=services.AddIdentityServer()
.AddDeveloperSigningCredential();
if(_config.GetSection(“AppSettings:UseDummyAuthentication”).Get())
{
标识服务器生成器
.AddInMemoryIdentityResources(_config.GetSection(“IdentityResources”))
.AddInMemoryApiResources(_config.GetSection(“ApiResources”))
.AddInMemoryClients(_config.GetSection(“客户端”))
.AddTestUsers(_config.GetSection(“TestUsers”));
}
services.AddAuthentication();
}

请帮帮我,伙计们!如果没有同意屏幕上的重定向,如何使Path=/tenant1方案工作?

好的,我找出了问题所在,并将答案发布给遇到相同问题的人。问题是,当您更改cookie IdentityServer的路径时,服务器的中间件找不到它,因为它位于。您需要为客户端上的每个租户处理此问题,并将所有这些URL添加到客户端重定向URI。 要实现它,您的多租户配置应该如下所示

            services.AddMultiTenant().WithInMemoryStore(Configuration.GetSection("MultiTenant:InMemoryStore"))
            .WithRouteStrategy(MapRoutes)
            .WithRemoteAuthentication()
            .WithPerTenantOptions<CookieAuthenticationOptions>((options, tenantContext) =>
            {
                options.Cookie.Name = $"auth.{tenantContext.Identifier}";
                options.Cookie.Path = "/" + tenantContext.Identifier;
                options.LoginPath = "/" + tenantContext.Identifier + "/Home/Login";
            })
            .WithPerTenantOptions<OpenIdConnectOptions>((opt, ctx) =>
            {
                opt.CallbackPath = "/" + ctx.Identifier + "/signin-oidc";
            });

你好我使用的方法和你一样,但我在一点上卡住了。当我尝试访问租户1时,系统将我重定向到identity service(由identity Server 4和ASP.NET Core identity framework实现)登录页面。成功登录后,它将我重定向回MVC应用程序。现在,当我尝试访问另一个租户(例如租户2)时,它会将我重定向到identity server的“授权”端点。它实际上是使用asp.net核心标识cookie将用户重定向到授权端点。您能帮助我如何登陆用户登录页面吗?您好,@BilalHashmi没有代码很难说,但我认为在访问租户2后,您的用户应该在同意屏幕上重定向。一旦允许,租户2应在未经同意的情况下被允许。这是正常的行为,我认为用户不应该每次都登录。但如果您愿意,您应该使用会话cookie。它应该是特定于租户域的。请朝那个方向看一看谢谢你的反馈。我已通过在IdentityServer4端侦听identity cookie选项上的事件(OnValidatePrincipal)修复了该问题。在事件处理程序中,我比较用户关联的租户和acr_值中接收到的租户信息。如果不匹配,我拒绝委托人。@BilalHashmi great:)
            services.AddMultiTenant().WithInMemoryStore(Configuration.GetSection("MultiTenant:InMemoryStore"))
            .WithRouteStrategy(MapRoutes)
            .WithRemoteAuthentication()
            .WithPerTenantOptions<CookieAuthenticationOptions>((options, tenantContext) =>
            {
                options.Cookie.Name = $"auth.{tenantContext.Identifier}";
                options.Cookie.Path = "/" + tenantContext.Identifier;
                options.LoginPath = "/" + tenantContext.Identifier + "/Home/Login";
            })
            .WithPerTenantOptions<OpenIdConnectOptions>((opt, ctx) =>
            {
                opt.CallbackPath = "/" + ctx.Identifier + "/signin-oidc";
            });
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

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

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        services.AddMultiTenant().WithInMemoryStore(Configuration.GetSection("MultiTenant:InMemoryStore"))
            .WithRouteStrategy(MapRoutes)
            .WithRemoteAuthentication()
            .WithPerTenantOptions<CookieAuthenticationOptions>((options, tenantContext) =>
            {
                options.Cookie.Name = $"auth.{tenantContext.Identifier}";
                options.Cookie.Path = "/" + tenantContext.Identifier;
                options.LoginPath = "/" + tenantContext.Identifier + "/Home/Login";
            })
            .WithPerTenantOptions<OpenIdConnectOptions>((opt, ctx) =>
            {
                opt.CallbackPath = "/" + ctx.Identifier + "/signin-oidc";
            }); ;

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
            {
                o.Cookie.Name = "auth.";
                o.Cookie.IsEssential = true;
            })
        .AddOpenIdConnect("oidc", options =>
        {
            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.Authority = "https://localhost:5000";

            options.ClientId = "mvc";
            options.SaveTokens = true;

            options.ClientSecret = "secret";
            //Hybrid protocols (OpenId + OAuth)
            options.ResponseType = OpenIdConnectResponseType.CodeIdToken;

            options.GetClaimsFromUserInfoEndpoint = true;
            //ask to allow access to testApi
            options.Scope.Add("testApi");
            //allows requesting refresh tokens for long lived API access
            options.Scope.Add("offline_access");

            options.Events = new OpenIdConnectEvents()
            {
                OnRedirectToIdentityProvider = ctx =>
                {
                    var tenant = ctx.HttpContext.GetMultiTenantContext()?.TenantInfo?.Identifier;
                    ctx.ProtocolMessage.AcrValues = $"tenant:{tenant}";
                    return Task.FromResult(0);
                }
            };
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            var errorPage = Configuration.GetValue<string>("ErrorPage");
            app.UseExceptionHandler(errorPage);
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseMultiTenant();
        app.UseAuthentication();
        app.UseMvc(MapRoutes);
    }

    private void MapRoutes(IRouteBuilder router)
    {
        router.MapRoute("Default", "{__tenant__=tenant1}/{controller=Home}/{action=Index}/{id?}");
    }
"redirectUris": [ "https://localhost:5002/tenant1/signin-oidc", "https://localhost:5002/tenant2/signin-oidc", "https://localhost:5002/tenant3/signin-oidc" ]