简体   繁体   中英

.Net Core 2.0 - Azure Active Directory - NGinX reverse Proxy - HTTPS

I have a .NET Core 2.0 website, running on Linux, listening on port 5000, behind an NGinX reverse proxy, which is listening on port 80 and 442. NGinX is configured to redirect HTTP traffic to HTTPS, and handle all communication over HTTPS. The NGinx Reverse Proxy and Asp.Net Core app are within their own docker containers, on a shared network.

This setup is currently working as described.

However, I would now like to Authenticate my users against our Azure Active Directory. I have run into a problem and don't know where to go from here.

First, let me show you how I have most of this configured, and then I'll explain my error.

NGinx (nginx.conf)

worker_processes 2;

events { worker_connections 1024; }

http {
    sendfile on;

    upstream docker-dotnet {
        server mycomp_prod:5000;
    }

    server {
            listen 80;
            server_name sales.mycompany.com;
            return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;
        server_name sales.mycompany.com;
        ssl_certificate     /etc/nginx/ssl/combined.crt;
        ssl_certificate_key /etc/nginx/ssl/salesmycompany.key;

        location / {
            proxy_pass         http://docker-dotnet;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
        }
    }

}

Dotnet:Startup.cs ConfigureServices()

services.AddAuthentication(sharedOptions =>
{
     sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
     sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie();

Dotnet:Startup.cs Configure()

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

Dotnet: appsettings.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "mycompany.com",
    "TenantId": "my-tenant-id",
    "ClientId": "my-client-id",
    "CallbackPath": "/signin-oidc"
  },

In My Azure Active Directory Tentant

I have configured 2 "Reply URLs"

Now for the error / My Question

When I hit the site, I sign in. Afterward signing in, and choosing whether or not to "Stay signed in", I'm taken to a page with an error.

在此输入图像描述

You can see in the error, that the Reply Address that is attempting to be redirected to, is HTTP, not HTTPS. I think this is coming from the line in appsettings.json that says:

"CallbackPath": "/signin-oidc"

And since my .NET Core Site (via Kestrel on port 5000) is not on HTTPS, it's trying to load http://example.com /signin-oidc , instead of HTTPS. Remember that my .NET Core Site is behind an NGinX reverse Proxy, which is configured to handle traffic on 443.

Thank you,

I saw this and was able to get it working: https://github.com/aspnet/Security/issues/1702

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

        app.UseForwardedHeaders(fordwardedHeaderOptions);

You should check out the documentation on Hosting on Linux .

Make sure you use UseForwardedHeaders in the middleware pipeline before UseAuthentication :

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

app.UseAuthentication();

Nginx will assign a header for the protocol used before it forwarded the call to Kestrel (among other things). This middleware will then check those headers to set the right protocol.

In startup.cs, you can try to force hostname and schema. The following code could help. Important: place it before setting authentication.

app.Use((context, next) =>
{
   context.Request.Host = new HostString(hostname + (port.HasValue ? ":" + port : null));
   context.Request.Scheme = protocol;
   return next();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM