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?
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, Stack
1 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(ReadOnlyMemory
1 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(ReadOnlyMemory
1 source, CancellationToken cancellationToken) at Microsoft.AspNetCore.Watch.BrowserRefresh.ResponseStreamWrapper.WriteAsync(ReadOnlyMemory1 buffer, CancellationToken cancellationToken) in /_3/ResponseStreamWrapper.cs:line 92at Microsoft.WebTools.BrowserLink.Net.ResponseStreamWrapper.WriteAsync(ReadOnlyMemory
1 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](IHttpApplication
1 application)Here's my Program.cs file for setting up web adapters/Yarp:
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?