如何在负载均衡器后面配置UseCookieAuthentication

时间:2017-04-06 23:05:44

标签: c# identityserver3 identityserver4 oidc

我正在配置.netcore应用程序以使用OIDC身份验证(由IdentityServer提供)。

我在StartUp中包含了以下代码

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "Cookies",
    AutomaticAuthenticate = true,
    ExpireTimeSpan = TimeSpan.FromMinutes(60)
});

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    AuthenticationScheme = "oidc",
    SignInScheme = "Cookies",

    Authority = "https://myauthority",
    ClientId = "myclient",
    CallbackPath = "/",
    ResponseType = "id_token token",
    Scope = { "openid", "profile", "email" },
});

应用程序托管在AWS上,在ECS中运行的docker中。它运行在监听https的应用程序负载均衡器后面。

我发现由于我的应用程序本身并不使用https(因为https由负载均衡器终止),OIDC中间件在重定向到OIDC服务器时会生成错误的返回URL - 它生成的URL开始http: //.

返回URL由AuthenticationHandler基类中名为BuildRedirectUri的方法生成。它只是使用它收到请求的协议 - 似乎没有办法覆盖它。

protected string BuildRedirectUri(string targetPath)
{
    return this.Request.Scheme + "://" + this.Request.Host + this.OriginalPathBase + targetPath;
}

所以鉴于它似乎没有可能配置中间件来强制HTTP重定向,我还有其他选择吗?

我应该写一个更高的'中间件组件监听重定向请求和修改协议?或者有更好的方法来解决这个问题吗?

2 个答案:

答案 0 :(得分:3)

当使用代理时(例如将IIS放在Kestrel前面或在您的情况下,将负载平衡器放在其中),代理应该发送X-Forwarded-ForX-Forwarded-Proto HTTP标头。它是后一个传递请求的原始协议。幸运的是有一个解决方案,那就是使用Microsoft.AspNetCore.HttpOverrides包中的Wrapper2中间件。因此,添加该包,然后将此代码添加到中间件管道:

ForwardedHeaders

尽早将其置于您的管道中。

答案 1 :(得分:1)

对我来说,添加ForwarededHeaders是不够的。我还必须添加以清除网络和代理(如on the ASP.NET Core Docs repo所述)。

并尽早在Configure中这样做:

 var options = new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        };
 options.KnownNetworks.Clear();
 options.KnownProxies.Clear();
 app.UseForwardedHeaders(options);

如果其他所有方法都失败了,您也可以通过使用https://leastprivilege.com/2017/10/09/new-in-identityserver4-v2-simplified-configuration-behind-load-balancers-or-reverse-proxies/发布的解决方案来避免所有这些情况。也可以(但不适用于我的多租户环境):

services.AddIdentityServer(options =>
            {
                ...
               options.PublicOrigin = "https://whatever.domain.com";
                ...
            })