Server Side Blazor Asp.Net Identity SignInAsync error : The response headers cannot be modified

Viewed 5383

I'm trying to get the Asp.Net Identity login working through Blazor in the Visual Studio template application it still uses Razor Pages and MVC to login, but can only get it to work on the event OnInitAsync, which is not useful because it needs to be done on a button click and not when the page is loading.

My failing code is

protected async Task LoginTest()
{
   await _SignInManager.SignInAsync(new ApplicationUser()
   { UserName = "test@test.com" }, true);
   UriHelper.NavigateTo("/", true);
}

I get the error:

System.InvalidOperationException: The response headers cannot be modified because the response has already started.
at Microsoft.AspNetCore.HttpSys.Internal.HeaderCollection.ThrowIfReadOnly()
at Microsoft.AspNetCore.HttpSys.Internal.HeaderCollection.set_Item(String key, StringValues value)
at Microsoft.AspNetCore.Http.Internal.ResponseCookies.Append(String key, String value, CookieOptions options)
at Microsoft.AspNetCore.Authentication.Cookies.ChunkingCookieManager.AppendResponseCookie(HttpContext context, String key, String value, CookieOptions options)
at Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler.HandleSignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, String scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
at Microsoft.AspNetCore.Identity.SignInManager`1.SignInWithClaimsAsync(TUser user, AuthenticationProperties authenticationProperties, IEnumerable`1 additionalClaims)
at WebApplication3.Pages.Account.Login.RegUser() in C:\Users\david\source\repos\WebApplication3\WebApplication3\Pages\Account\Login.razor:line 28
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.Rendering.Renderer.GetErrorHandledTask(Task taskToHandle)

Has anyone had any success in getting this working? As I mentioned I can get it to work if I put the above function inside the OnInitAsync method but it's no good doing it there.

Any help would be much appreciated.

2 Answers

After reading David Hawkins post and some digging, I found a workaround solution as he described on https://github.com/dotnet/aspnetcore/issues/13601#issuecomment-679870698. Simple and effective.

In the proposed solution, there is no encryption of the user/password details in the middleware, as it stays on the server.

As of now (April 2021) it doesn't seems if ASP.Net Core 5 and Identity supports Blazor calling SignInManager's *SignIn methods. By the time it is called, the HTTP headers have already been send and cannot be modified/appended too.

I found this related GitHub issue http://github.com/aspnet/AspNetCore/issues/11411

I ended up creating a work-around solution using the post-redirect-get approach. In the post I encrypted a login token with the user details and passed it to another page as a get with the token in the querystring, then I read the encrypted token and login the user.

Related