My ASP.NET Core app uses "out-of-box" external login authentication. What I want to implement - on facebook challenge I want to wrap redirect url and return it as json to consume in jquery frontend. But after request ends I see 500 error in browser and next error in application console:
fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLV651D6KVJC", Request id "0HLV651D6KVJC:00000005": An unhandled exception was thrown by the application. System.InvalidOperationException: Response Content-Length mismatch: too few bytes written (0 of 470).
My external login action, nothing special to look at
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
Facebook authentication configuration:
services.AddAuthentication().AddFacebook(facebookOptions =>
{
facebookOptions.AppId = Configuration["Authentication:Facebook:AppId"];
facebookOptions.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
facebookOptions.Events.OnRedirectToAuthorizationEndpoint =
async (x) =>
{
UTF8Encoding encoding = new UTF8Encoding();
var content = JsonConvert.SerializeObject(new { redirect_url = x.RedirectUri });
byte[] bytes = encoding.GetBytes(content);
x.Response.StatusCode = 200;
x.Response.ContentLength = bytes.Length;
x.Response.ContentType = "text/plain";
x.Response.Body = new MemoryStream();
await x.Response.WriteAsync(content);
// at this point I see that x.Response.Body.Length == 470, but message states there are 0 of 470 written
};
});
Is there any way I could make it work?
This can also happen when using new C# using
syntax like this:
using var ms = new MemoryStream();
using var writer = new StreamWriter(ms);
writer.WriteLine("my content");
memoryStream.Position = 0;
return File(ms, "text/plain");
in this case, the MemoryStream
is accessed before the StreamWriter
is flushed. Either use old syntax for the StreamWriter
:
using var ms = new MemoryStream();
using (var writer = new StreamWriter(ms, Encoding.UTF8, -1, true))
{
writer.WriteLine("my content");
}
memoryStream.Position = 0;
return File(ms, "text/plain");
or flush the writer:
using var ms = new MemoryStream();
using var writer = new StreamWriter(ms);
writer.WriteLine("my content");
writer.Flush();
memoryStream.Position = 0;
return File(ms, "text/plain");
Changed code to write to original response stream and it works now.
facebookOptions.Events.OnRedirectToAuthorizationEndpoint =
async (x) =>
{
var content = JsonConvert.SerializeObject(new { redirect_url = x.RedirectUri });
x.Response.StatusCode = 200;
x.Response.ContentType = "text/plain";
await x.Response.WriteAsync(content);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With