aspnet / BasicMiddleware

[Archived] Basic middleware components for ASP.NET Core. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
169 stars 84 forks source link

Request.Scheme is still http even though using HttpOverrides #268

Closed tanaka-takayoshi closed 6 years ago

tanaka-takayoshi commented 7 years ago

We sometimes want Request.Scheme should be https behind front-end load balancer (nginx, haproxy and so on). In this situation, the front-end serves with https, terminates SSL then load-balances with http. In this situation, the backend ASP.NET Core web server listens to only http request. However, we want Request,Scheme should be https to create a redirect URL for Identity such as Azure AD B2C, Open ID Connect and so on. For this purpose, the front-end load balancer adds X-Forwarded-Proto with https.

I expect Microsoft.AspNetCore.HttpOverrides set Request.Scheme to https when X-Forwarded-Proto is https. https://www.nuget.org/packages/Microsoft.AspNetCore.HttpOverrides/

Though I configure HttpOverrides as follows, I still get Request.Scheme is http in a Controller class.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //not enough
    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.XForwardedProto
     });
    //...
}

To workaround this, I can get Request.Scheme is https by adding below codes.

    app.Use((context, next) =>
     {
        if (context.Request.Headers.TryGetValue(XForwardedPathBase, out StringValues pathBase))
        {
            context.Request.PathBase = new PathString(pathBase);
        }

        if (context.Request.Headers.TryGetValue(XForwardedProto, out StringValues proto))
        {
            context.Request.Protocol = proto;
        }
         return next();
    });

I found this workaround from https://github.com/aspnet/Docs/issues/2384#issuecomment-286146843

Also, I wonder whether it's a HttpOverrides librars's issue or not. If this is not a right place. could tell me the right place?

Tratcher commented 7 years ago

Which version of HttpOverrides are you using? A default setting was relaxed in 2.0 and it addressed many of the issues people have here.

Also, please share the request headers as received by the application. That will help us determine why the forwarded headers were not applied.

tanaka-takayoshi commented 7 years ago

Yes, the version is 2.0.0.

    <PackageReference Include="Microsoft.AspNetCore.HttpOverrides">
      <Version>2.0.0</Version>
    </PackageReference>

Here are the all headers

Accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding=gzip, deflate, br
Accept-Language=ja,en-US;q=0.8,en;q=0.6
Cookie=__utma=144897195.1338814121.1504445461.1504445461.1504530945.2; __utmz=144897195.1504530945.2.2.utmcsr=google\|utmccn=(organic)\|utmcmd=organic\|utmctr=(not%20provided)
Host=repro.52.175.232.56.nip.io
Referer=https://repro.52.175.232.56.nip.io/
User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Upgrade-Insecure-Requests=1
X-Forwarded-Host=repro.52.175.232.56.nip.io
X-Forwarded-Port=443
Forwarded=for=124.212.187.199;host=repro.52.175.232.56.nip.io;proto=https
X-Forwarded-For=124.212.187.199
X-Original-Proto=http
Scheme: https
Tratcher commented 7 years ago

Were those headers enumerated within your controller? Or are they from a network trace between nginx and kestrel? The presence of the "X-Original-Proto=http" header implies the "X-Forwarded-For" header was successfully processed and removed.

There are several parts of your explanation that don't make sense. "I still get Request.Scheme is https in a Controller class." was that a typo? I thought https was what you wanted?

Setting Request.Protocol to https also doesn't make sense, Protocol is the HTTP version, e.g. HTTP/1.1.

tanaka-takayoshi commented 7 years ago

There are several parts of your explanation that don't make sense. "I still get Request.Scheme is https in a Controller class." was that a typo? I thought https was what you wanted? Yes, that was typo. I have fixed my comment.

Setting Request.Protocol to https also doesn't make sense, Protocol is the HTTP version, e.g. HTTP/1.1. The workaround code was originated by another person. I'll test it again later.

tanaka-takayoshi commented 7 years ago

I may miss-understood the situation. I have found the httpoverrides works correctly as follows. https://github.com/tanaka-takayoshi/httpoverrides-test/tree/httpoverrides-only

It seems another thing may affect my original issue. This issue can be closed at this time, and I'll reopen if I find the root cause.