I have an ASP.NET Core MVC application. If I'm doing a AJAX POST with dataType: "json"
, and I return a Forbid()
then I always get a 400 Bad Request
instead of returning 403 Forbidden
. But in case of a GET-Request the 403 Forbidden
is returned
Following Example - I'm using .NET Core 6 with this startup-script:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseExceptionHandler("/Error/");
app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseMiddleware<SerilogMiddleware>();
app.UseSerilogRequestLogging();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization();
});
}
Controller:
public class HomeController : Controller
{
public ActionResult Get()
{
return Forbid();
}
[HttpPost]
[IgnoreAntiforgeryToken] //just for demo to keep it simple
public ActionResult Post()
{
return Forbid();
}
}
Ajax-Requests:
$.ajax({
type: "GET",
url: "Home/Get",
dataType: "json",
contentType: "application/json",
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.status);
},
success: function() {
console.log('success');
}
});
$.ajax({
type: "POST",
url: "Home/Post",
dataType: "json",
contentType: "application/json",
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.status);
},
success: function() {
console.log('success');
}
});
The GET-Request returns a 403 Forbidden
, the POST-Request returns a 400 Bad Request
.
Why isn't the POST-Request also returning an 403 Forbidden
? If I don't set the dataType
and the contentType
, then the POST-Request also returns a 403 Forbidden
.
Especially I also want to handle 403 Forbidden
and 401 Unauthorized
on JSON-Ajax calls. How can I achieve this?
CodePudding user response:
If I don't set the dataType and the contentType, then the POST-Request also returns a 403 Forbidden.
That's the key to figuring out what's going on. You are setting content type to application/json, but you are sending an empty body. Empty bodies are not valid JSON
In ASP.NET the content negotiation (the bit that deserializes your inputs. Runs before the controller body. If it fails, it will 400 or 405 depending on the source of the failure.