在ASP.NET Core中关联失败

时间:2018-08-03 07:34:24

标签: asp.net-core azure-service-fabric openid-connect azure-ad-b2c traefik

我的Web应用程序无法使用OpenIdConnect进行身份验证。目前,我在OnRemoteFailure上看到“关联失败”错误。

上下文:

  • Service Fabric无状态.net核心Web应用程序
  • 天青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?}");
        });
    }

控制器:

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
        {
            (...)
        }
    }
    (...)
}

事件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

成功,然后POST请求失败:

https://{external_url}/{external_path}/signin-oidc

此POST包含表单数据id_tokenstate

在B2C中配置的重定向URL为https://{external_url}/{external_path}/signin-oidc。我也尝试过https://{external_url}/{external_path},但效果不佳。

我尝试使用转发标题,但没有帮助。

谁能指出我所缺少的东西?

谢谢!

1 个答案:

答案 0 :(得分:5)

我发现了问题。问题出在中间件的顺序上。身份验证中间件必须在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?}");
    });
}