Reputation: 399
I have a web project using ASP .Net Core 2.2 that has anti-forgery token validation. After that all my AJAX post requests are not working. Is there any way to execute this AJAX request with minimal changes?
$.ajax({
type: 'POST',
url: 'Register/RegisterNewUser',
data: {
Name: "John",
Surname: "Doe",
Email: "[email protected]"
},
success: success,
error: function(xhr, textStatus, errorThrown) {
alert(errorThrown);
}
});
Upvotes: 0
Views: 2152
Reputation: 1007
First, you need to configure the Middleware
TestMiddleware.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
namespace Test.Middleware
{
public class TestMiddleware
{
private readonly RequestDelegate _next;
public TestMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext, AppDbContext dataContext, UserManager<User> userManager, IAntiforgery antiforgery)
{
SetAntiForgeryTokenCookie();
// Move forward into the pipeline
await _next(httpContext);
}
private void SetAntiForgeryTokenCookie(HttpContext httpContext, IAntiforgery antiforgery)
{
var tokens = antiforgery.GetAndStoreTokens(httpContext);
httpContext.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
}
}
public static class TestMiddlewareExtensions
{
public static IApplicationBuilder UseTestMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<TestMiddleware>();
}
}
#endregion
}
Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Test.Middleware;
namespace Test
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Database"), b => b.MigrationsAssembly("Test")));
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(480);
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/AccessDenied";
options.SlidingExpiration = true;
});
services.AddAntiforgery(options =>
{
// Antiforgety settings
options.HeaderName = "X-CSRF-TOKEN";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseTestMiddleware();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
script.js
self.saveSurvey = function (userId) {
var csrfToken = self.getCookie("CSRF-TOKEN");
var ajaxUrl = "Account/Save",
ajaxData = {
UserId: userId
};
$.ajax({
type: "POST",
url: ajaxUrl,
data: JSON.stringify(ajaxData),
cache: false,
contentType: "application/json; charset=utf-8",
dataType: 'json',
headers: {
"X-CSRF-TOKEN": csrfToken
},
success: function (viewModel) {
console.log("Eureka!")
},
error: function (error) {
console.log("Not Eureka!")
}
});
};
Upvotes: 0
Reputation: 399
Solution:
@using Microsoft.AspNetCore.Antiforgery
@inject IAntiforgery Antiforgery
<!---Some content ---->## Heading ##
<script>
$.ajax({
type: 'POST',
beforeSend: function (request) { request.setRequestHeader("RequestVerificationToken",@Antiforgery.GetTokens(Context).RequestToken);},
url: 'Register/RegisterNewUser',
data: { Name: "John", Surname:"Doe",Email:"[email protected]" },
success: success,
error: function (xhr, textStatus, errorThrown) { alert(errorThrown);}
});
</script>
Upvotes: 0
Reputation: 352
You could post antiforgerytoken validation with header of your request with .net core 2.2
$.ajax({
type: 'POST',
url: 'Register/RegisterNewUser',
dataType: 'json',
data: { Name: "John", Surname: "Doe", Email: "[email protected]" },
headers: {
RequestVerificationToken:
$('input:hidden[name="__RequestVerificationToken"]').val()
},
success: success,
error: function (xhr, textStatus, errorThrown)
{
alert(errorThrown);
}
});
Upvotes: 2