How to configure UseCookieAuthentication behind a load balancer
Asked Answered
T

2

5

I am configuring a .netcore application to use OIDC authenication (provided by IdentityServer).

I have included the following code in my 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" },
});

The application is hosted on AWS, within a docker running in ECS. It runs behind an application load balancer listening on https.

I have found that because my application is not itself using https (because the https is terminated by the load balancer), the OIDC middleware is generating an incorrect return URL when redirecting to the OIDC server - the URL it generates begins http://.

The return URL is generated by a method named BuildRedirectUri within the AuthenticationHandler base class. It just uses the protocol on which it received the request - there doesn't seem any way to override this.

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

So given it doesn't seem possible to configure the middleware to force a HTTP redirect, what other options do I have?

Should I write a 'higher' middleware component to listen for redirect requests and modify the protocol? Or is there a better way to solve this problem?

Toot answered 6/4, 2017 at 23:5 Comment(1)
Were you able to solve this? I'm encountering the same scenario and, as you commented on the answer supplied by @davidg adding the middleware doesn't seem to have an effect.Leptorrhine
R
4

When a proxy is used (for example putting IIS in front of Kestrel or as in your case, a load balancer), the proxy should be sending X-Forwarded-For and X-Forwarded-Proto HTTP headers. It's the latter one that passes along the original protocol that was requested. Fortunately there is a solution, and that is to use the ForwardedHeaders middleware from the Microsoft.AspNetCore.HttpOverrides package. So add that package and then add this code to your middleware pipeline:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

Place this as early as you can in your pipeline.

Retrace answered 6/4, 2017 at 23:34 Comment(2)
This doesn't seem to make any difference to the .net core OIDC middleware. Are there any other steps involved?Householder
While this is a good answer, I only needed the ForwardedHeaders.XForwardedProto header.Generation
B
3

For me, adding the ForwarededHeaders wasn't enough. I had to add to clear the networks and proxies as well (as noted on the ASP.NET Core Docs repo).

And do so as early as possible in Configure:

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

If all else fails you can also avoid all this by using the solution posted https://leastprivilege.com/2017/10/09/new-in-identityserver4-v2-simplified-configuration-behind-load-balancers-or-reverse-proxies/. Which also worked (but not for my multi-tenant environment):

services.AddIdentityServer(options =>
            {
                ...
               options.PublicOrigin = "https://whatever.domain.com";
                ...
            })
Borrego answered 4/4, 2019 at 23:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.