Reputation: 779
In my ASP.NET Core 2 WebAPI application I want to use the AntiforgeryToken for my POST, PUT and DELETE controller methods. Reagrding to this documentation I set up the ConfigureServices
and Configure
methods of my Startup
class. On the client side I use Angular 5 and their default configuration for Antiforgery. I can't figure out where the problem is.
Here is a excerpt of my Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAntiforgery(options =>
{
options.Cookie.Name = "XSRF-TOKEN";
options.HeaderName = "X-XSRF-TOKEN";
options.FormFieldName = "F-XSFR-TOKEN";
});
// ...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider provider, ILogger<Startup> logger, IAntiforgery antiforgery)
{
// ...
app.Use(async (context, next) =>
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
await next();
});
// ...
}
My Controllers are all like that one:
[Authorize]
[Route("api")]
public class CarController : Controller
{
#region Variables
private readonly DataContext _db;
private ILogger<CarController> _logger;
#endregion
#region Constructor
public CarController(DataContext db, ILogger<CarController> logger)
{
_db = db;
_logger = logger;
}
#endregion
#region Methods
[AllowAnonymous]
[HttpGet("[controller]")]
public IActionResult Get()
{
try
{
return Ok(_db.Cars);
}
catch (Exception ex)
{
_logger.LogError(ex.GetHashCode(), ex, ex.Message);
return BadRequest(ex);
}
}
[HttpPost("[controller]")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Post([FromBody] CreateCar model)
{
try
{
// Creates a new car.
}
catch (Exception ex)
{
_logger.LogError(ex.HResult, ex, ex.Message);
return StatusCode(500, ex);
}
}
[HttpPut("[controller]/{id}")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Put(int id, [FromBody] UpdateCar model)
{
try
{
// Updates a car
}
catch (Exception ex)
{
_logger.LogError(ex.HResult, ex, ex.Message);
return StatusCode(500, ex);
}
}
#endregion
}
Upvotes: 2
Views: 1220
Reputation: 858
I hit the same problem and I think I found the issue.
TLDR: options.Cookie.Name = "ASP-XSRF-TOKEN";
The options.Cookie.Name
in the AddAntiforgery
has to be different than the cookie you set manually using context.Response.Cookies.Append
.
Try to change the name of one of them and it will work. Right now you override the generated cookie that is using the options.Cookie.Name
name with the tokens.RequestToken
value.
You can notice the difference in the Developer Tools.
options.Cookie.Name
is marked as http only
(HttpOnly = true
)context.Response.Cookies.Append
is marked as HttpOnly = false
The second one is read from JS/Angular (you can read it in JS because the HttpOnly=false
and sent as a header in your ajax requests and validated against the default one that can't be read from JS)
Upvotes: 3