简体   繁体   中英

WebApp behind IIS reverse proxy sets wrong signin_oidc redirect_uri while authenticating against external IdentityServer via OIDC

I'm hosting an asp.net core application ( admin ) behind an IIS server configured as a reverse proxy. The app uses open id connect to authenticate users against a separate application ( core ) which uses Identity Server 4 (also hosted behind the same reverse proxy). Both apps are using .NET Core 3.1. The reverse proxy is configured to forward requests for http://192.168.0.161/admin to the admin app which is hosted on the same machine under http://localhost:44321 . This works so far until a user tries to login. The user gets correctly redirected to the core apps login page but this redirect does contain the wrong signin_oidc redirect uri to redirect back to the admin app. The signin_oidc redirect uri gets always set to http://localhost:44321/signin-oidc instead of http://192.168.0.161/admin/signin-oidc .
I already searched around the internet but every solution I found tells me to configure the ForwardedHeadersOptions and call app.UseForwardedHeaders() before app.UseAuthentication() and everything else should be handled automatically. But it doesn't.
It seems like the application does not take those headers into account.

Code for admin app:

Startup/ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = "oidc";
        })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddOpenIdConnect("oidc", options =>
        {
            options.Authority = openIdConnectAuthority;

            options.ClientId = "mvc";
            options.ClientSecret = "secret";
            options.ResponseType = OidcConstants.ResponseTypes.Code;

            options.SaveTokens = true;

            options.GetClaimsFromUserInfoEndpoint = true;
            options.RequireHttpsMetadata = false;
        });

        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders = ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
        });

        ...
}

Startup/Configure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseForwardedHeaders();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
        endpoints.MapRazorPages();
    });
}

When I debug the application these are the relevant request headers which are sent to the app:

{[X-Forwarded-Host, {192.168.0.161}]}
{[X-Forwarded-Proto, {http}]}
{[X-Original-URL, {/admin}]}
{[X-Forwarded-For, {192.168.0.161:51920}]}

What am I doing wrong? How can I tell the open id connect middleware to take those headers into account or at least hard code the signin_oidc return url? Because setting the CallbackPath for oidc does only allow relative urls, so no chance of changing the base path.

Edit
I also tried overriding the OnRedirectToIdentityProvider event in AddOpenIdConnect() and setting the return url manually like this:

options.Events.OnRedirectToIdentityProvider = ctx =>
{
    ctx.ProtocolMessage.RedirectUri = "http://192.168.0.161/admin/signin-oidc";
    return Task.CompletedTask;
};

But this will result in a

Correlation failed. Unknown location.

exception on redirect.

Edit 2

The

Correlation failed. Unknown location.

exception disappeared without me knowingly doing anything different. Which means I will go with this solution for the moment.

I ran into this scenario when trying to login using an external provider on an Android device and running the web service locally on my PC. I had to use a proxy address since Android doesn't know to forward the localhost calls to the PC. I am using AddMicrosoftIdentityWebApp instead of AddOpenIdConnect but they are very similar.

.AddMicrosoftIdentityWebApp(options =>
{
       Configuration.Bind("AzureAd", options);
       options.SaveTokens = true;
       options.Events.OnRedirectToIdentityProvider = context =>
       {
          context.ProtocolMessage.RedirectUri = "https://192.168.1.138:45455/signin-oidc";
          return Task.CompletedTask;
       };
    })
.EnableTokenAcquisitionToCallDownstreamApi( 
           options=> { 
              options.RedirectUri= "https://192.168.1.138:45455/signin-oidc";
           },
           initialScopes: GraphConstants.Scopes)

I was also getting the Correlation failed. Unknown location. error when trying to login on the PC. I noticed if the login page was loaded using the local host URL and the redirect was set to the 192.168 address this error would occur. Launching the login page using the 192.168 address stopped that error from happening.

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