Skip to content

System.InvalidOperationException: Multiple Location headers were detected. This is possibly because you have remote authentication as the default scheme. Consider short circuiting the YARP requests or disabling default scheme. #671

Description

@htmlsplash

All,

I have encountered a problem with my setup.

My Setup:

We use Strangler fig pattern to migrate our legacy web forms application to asp.net Core Blazor application.
For this we use:
Yarp - Proxy requests to legacy webforms app
Web Adapters - For porting code, and setup remote client authentication

When an unauthenticated user clicks on a link in the Blazor application that refers to a protected page in Webforms application, Yarp will forward this request to the webforms application but since the user is not authenticated, there will be a redirect to the login page. During this redirect the following exception is thrown because Yarp and System Webadapters set the location header which causes Kestrel to blow up:

fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HNKKP0JMDQLS", Request id "0HNKKP0JMDQLS:00000005": An unhandled exception was thrown by the application. System.InvalidOperationException: Multiple Location headers were detected. This is possibly because you have remote authentication as the default scheme. Consider short circuiting the YARP requests or disabling default scheme. at Microsoft.AspNetCore.SystemWebAdapters.Authentication.RemoteAppAuthenticationAuthHandler.<>c.<GetRemoteAppAuthenticationResultAsync>b__5_0(Object state) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<FireOnStarting>g__ProcessEvents|240_0(HttpProtocol protocol, Stack1 events)
warn: Yarp.ReverseProxy.Forwarder.HttpForwarder[48]
ResponseBodyClient: The client reported an error when copying the response body.
System.ObjectDisposedException: The response has been aborted due to an unhandled application exception.
---> System.InvalidOperationException: Multiple Location headers were detected. This is possibly because you have remote authentication as the default scheme. Consider short circuiting the YARP requests or disabling default scheme.
at Microsoft.AspNetCore.SystemWebAdapters.Authentication.RemoteAppAuthenticationAuthHandler.<>c.b__5_0(Object state)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.g__ProcessEvents|240_0(HttpProtocol protocol, Stack1 events) --- End of inner exception stack trace --- at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FirstWriteAsyncInternal(ReadOnlyMemory1 data, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.WritePipeAsync(ReadOnlyMemory1 data, CancellationToken cancellationToken) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponsePipeWriter.WriteAsync(ReadOnlyMemory1 source, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.WriteAsync(ReadOnlyMemory1 source, CancellationToken cancellationToken) at Microsoft.AspNetCore.Watch.BrowserRefresh.ResponseStreamWrapper.WriteAsync(ReadOnlyMemory1 buffer, CancellationToken cancellationToken) in /_3/ResponseStreamWrapper.cs:line 92
at Microsoft.WebTools.BrowserLink.Net.ResponseStreamWrapper.WriteAsync(ReadOnlyMemory1 buffer, CancellationToken cancellationToken) at Yarp.ReverseProxy.Forwarder.StreamCopier.CopyAsync(Stream input, Stream output, Int64 promisedContentLength, StreamCopierTelemetry telemetry, ActivityCancellationTokenSource activityToken, Boolean autoFlush, CancellationToken cancellation) fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HNKKP0JMDQLS", Request id "0HNKKP0JMDQLS:00000005": An unhandled exception was thrown by the application. System.ObjectDisposedException: The response has been aborted due to an unhandled application exception. ---> System.InvalidOperationException: Multiple Location headers were detected. This is possibly because you have remote authentication as the default scheme. Consider short circuiting the YARP requests or disabling default scheme. at Microsoft.AspNetCore.SystemWebAdapters.Authentication.RemoteAppAuthenticationAuthHandler.<>c.<GetRemoteAppAuthenticationResultAsync>b__5_0(Object state) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.<FireOnStarting>g__ProcessEvents|240_0(HttpProtocol protocol, Stack1 events)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.InitializeResponseAsync(Int32 firstWriteByteCount)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.FlushPipeAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.FlushAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Watch.BrowserRefresh.ResponseStreamWrapper.DisposeAsync() in /_3/ResponseStreamWrapper.cs:line 195
at Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware.InvokeAsync(HttpContext context) in /_3/BrowserRefreshMiddleware.cs:line 59
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application)

Here's my Program.cs file for setting up web adapters/Yarp:

builder.Services.AddSystemWebAdapters()   
    .AddRemoteAppClient(options =>
    {
        options.RemoteAppUrl = new(builder.Configuration["ProxyTo"]);
        options.ApiKey = builder.Configuration["RemoteAppApiKey"];
    })
    .AddAuthenticationClient(isDefaultScheme: true);

builder.Services.AddHttpForwarder();

app.UseSystemWebAdapters();

app.MapForwarder("/{**catch-all}", app.Configuration["ProxyTo"])
    .Add(static builder => ((RouteEndpointBuilder)builder).Order = int.MaxValue);`

I understand what the exception says but I am not sure of the "best" work around.
NOTE:
I still need to have "AddAuthenticationClient(isDefaultScheme: true)" be set to true because that's what populates my Identity object in the asp.net core application.

What is the best/recommended way to solve this problem?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs: Triage 🔍Label added to new issues which need Triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions