asp.net核心中的相关性失败

Joa*_*iro 5 openid-connect azure-service-fabric azure-ad-b2c asp.net-core traefik

我的Web应用程序无法使用OpenIdConnect进行身份验证.目前我看到"关联失败"错误OnRemoteFailure.

语境:

  • Service Fabric无状态.net核心Web应用程序
  • Azure B2C
  • 反向代理(Traefik)

启动:

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

        services.AddMvc();

        (...)

        services.AddAuthorization();
        services.AddAuthentication(sharedOptions =>
        {
            sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
        .AddCookie()
        .AddOpenIdConnect(o =>
        {
            o.ClientId = clientId;
            o.Authority = $"https://login.microsoftonline.com/{tenantId}/{signinPolicy}/v2.0";
            o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            o.SaveTokens = true;
            o.Events = new OpenIdConnectEvents
            {
                OnTokenValidated = async context =>
                {
                    (...)
                },
                OnRedirectToIdentityProvider = async context =>
                {
                    if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count > 0 &&
                    context.Request.Headers.TryGetValue("X-Forwarded-Host", out var hostValues) && hostValues.Count > 0 &&
                    context.Request.Headers.TryGetValue("X-Forwarded-Proto", out var protoValues) && protoValues.Count > 0)
                    {
                        // Use external URL and path
                        string redirectUri = $"{protoValues.First()}://{hostValues.First()}{prefix.First()}{context.Options.CallbackPath}";
                        context.ProtocolMessage.RedirectUri = redirectUri;
                    }
                },
                OnTokenResponseReceived = async context =>
                {
                },
                OnAuthenticationFailed = async context =>
                {
                },
                OnRemoteFailure = async context =>
                {
                }
            };
            o.ConfigurationManager = new PolicyConfigurationManager($"https://login.microsoftonline.com/{tenantId}/{signinPolicy}/v2.0",
                                      new[] { signinPolicy });
        });

        (...)
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseStaticFiles();

        app.UseAuthentication();

        app.Use(async (context, next) =>
        {
            if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count() > 0)
            {
                context.Request.PathBase = prefix.First();
            }
            await next.Invoke();
        });

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
Run Code Online (Sandbox Code Playgroud)

控制器:

public class AccountController : Controller
{
    [HttpGet]
    public IActionResult SignIn()
    {
        if (Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count() > 0)
        {
            return Challenge(new AuthenticationProperties { RedirectUri = prefix.First() }, OpenIdConnectDefaults.AuthenticationScheme);
        }
        else
        {
            (...)
        }
    }
    (...)
}
Run Code Online (Sandbox Code Playgroud)

该事件OnTokenValidated从未被解雇.

关于反向代理,它基本上将https:// internal_url:port/internal_path映射到https:// external_url/external_path.

我检查了请求,这是访问的GET:

https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize?p={signinPolicy}&client_id={clientId}&redirect_uri=https%3A%2F%2F{external_host}%2F{external_path}%2Fsignin-oidc&response_type=id_token&scope=openid%20profile&response_mode=form_post&nonce=(...)&x-client-SKU=ID_NET&x-client-ver=2.1.4.0
Run Code Online (Sandbox Code Playgroud)

它是成功的,然后失败的POST请求:

https://{external_url}/{external_path}/signin-oidc
Run Code Online (Sandbox Code Playgroud)

此POST包含表单数据id_tokenstate.

B2C中配置的重定向URL是https://{external_url}/{external_path}/signin-oidc.我也尝试了https://{external_url}/{external_path},但它也没有用.

我试图使用Forwarded Headers,但它没有帮助.

谁能指出我缺少的东西?

提前致谢!

Joa*_*iro 6

我发现了这个问题.问题在于中间件的顺序.身份验证中间件必须在PathBase上进行更改后进行.在我的情况下,不需要转发标头.

遵循固定Configure方法.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.Use(async (context, next) =>
    {
        if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count() > 0)
        {
            context.Request.PathBase = prefix.First();
        }
        await next.Invoke();
    });

    app.UseStaticFiles();

    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}
Run Code Online (Sandbox Code Playgroud)