Google Asp.Net Core Authentication

My application is running on Google Compute Engine. Nginx is used as a proxy server. Nginx is configured to use SSL. Below is the content of / etc / nginx / sites -available / default:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name mywebapp.com;
    return 301 https://$server_name$request_uri;
}
server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/ssl-mywebapp.com.conf;
    include snippets/ssl-params.conf;
    root /home/me/MyWebApp/wwwroot;
    location /.well-known/ {
    }
    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection keep-alive;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

      

In Startup.cs I have:

app.UseGoogleAuthentication(new GoogleOptions()
{
    ClientId = Configuration["Authentication:Google:ClientId"],
    ClientSecret = Configuration["Authentication:Google:ClientSecret"],
});

      

Now in Google Cloud Platform, I need to specify the authorized redirect URIs. If I enter the following, my web app works as expected:

http://mywebapp.com/signin-google

      

But it won't work if used https

; the browser displays the following error:

The redirect URI in the request, http://mywebapp.com/signin-google, does
not match the ones authorized for the OAuth client.

      

In this case, is it safe to use http as the allowed uri redirect? What configuration do I need if I want it to be https?

+3


source to share


1 answer


This is because your reverse proxy application has no idea that the request was originally coming over HTTPS.

SSL / TLS proxy protocol

The reverse proxy configuration described in the question is called an SSL / TLS reverse proxy. This means that secure traffic is established between the client and the proxy server. The proxy server decrypts the request and then redirects it to the application over HTTP.

The problem with this configuration is that the application behind it doesn't know that the client has sent the request over HTTPS. So when it comes to redirecting to itself, it uses HttpContext.Request.Scheme

, HttpContext.Request.Host

and HttpContext.Request.Port

to create a valid redirect URL.

X-Forwarded- * HTTP Headers

Headers are used here X-Forwarded-*

. In order for the application to know that the request initially goes through the proxy server over HTTPS, we must configure the proxy server to set the HTTP X-Forwarded-For

and X-Forwarded-Proto

.

location / {
    proxy_pass http://localhost:5000;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection keep-alive;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

      

OK, now if we go back to our ASP.NET Core app and look at the incoming HTTP request, we can see that the headers are set X-Forwarded-*

, however, the redirect URL still uses the HTTP scheme.

Redirected Middleware Headers

Basically this middleware overrides HttpContext.Request.Scheme

both the HttpContext.Connection.RemoteIpAddress

values ​​that were provided by the headers X-Forwarded-Proto

and X-Forwarded-For

appropriately. To make this happen, add it to the pipeline by adding the following line somewhere at the beginning of the method Startup.Configure()

.

        var forwardedHeadersOptions = new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto,
            RequireHeaderSymmetry = false
        };
        forwardedHeadersOptions.KnownNetworks.Clear();
        forwardedHeadersOptions.KnownProxies.Clear();

        app.UseForwardedHeaders(forwardedHeadersOptions);

      

Ultimately this should result in the correct URLs for your application being generated using the HTTPS scheme.



My story

The above code is different from what Microsoft suggests. If we look at the documentation , their code looks a little shorter:

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

      

However, this did not work for me. Also as per the comments in this question I am not alone.

I have nginx configured as a reverse proxy for an ASP.NET Core application running in a Docker container. This got complicated after I put everything behind Amazon Load Balancing (ELB).

I followed the documentation guidelines at first, but it didn't work for me. I have the following warning in my application:

Parameter mismatch between X-Forwarded-For and X-Forwarded-Proto

Then I looked at the titles X-Forwarded-*

and realized that they have different lengths. The header X-Forwarded-For

contained 2 entries (comma separated IP addresses) and X-Forwarded-Proto

only one entry https

. This is how I approached to set the property RequireHeaderSymmetry

to false

.

Well, I got rid of the "Parameter count ..." message, but right after that I ran into another odd debug message:

Unknown proxy: 172.17.0.6:44624

After going through the source code of ForwardedHeadersMiddleware , I finally figured out that I need to either clear both KnownNetworks

and the KnownProxies

collections, ForwardedHeadersOptions

or add my docker network 172.17.0.1/16

to the list of known networks. Right after that, I finally started working.

PS: For those setting SSL / TLS termination in a load balancer (like Amazon Load Balancer or ELB) DO NOT set the header X-Forwarded-Proto

in nginx config. This will override the correct value https

that comes from the load balance to the schema http

and the redirect url will be wrong. I have not yet found how to simply add the schema used in nginx to the header instead of overriding it.

+7


source







All Articles