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

@htmlsplash

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions