I created a Blazor .NET 8 project with auto. rendering and individual account authentication from Blazor WebApp template.
On the server side, I added an internal API with an [Authorize] attribute on the class and a POST method.
On the client side, I have a Razor page with a service that makes a POST request to the internal API using HttpClient.
I want to make sure that in my case, my API is protected against Cross-Site Request Forgery (CSRF) attacks. Does a Blazor project with individual account authentication automatically protect an internal API, or do I need to do something to secure it?
Server side / TestController.cs
namespace WebAppAutoIndividual.Controllers{ [ApiController] [Route("api/test2")] [Authorize] public class Test2Controller : Controller { private readonly ITest2Service _service; public Test2Controller(ITest2Service service) { _service = service ?? throw new ArgumentNullException(nameof(service)); } [HttpGet] public DataTest[] Read() { var items = _service.Get().Result; return items; } [HttpPost] public void Create([FromBody] DataTest dto) { _service.Add(dto); } }}Client side / page.razor
@page "/form-auto-controller"@attribute [Authorize]@rendermode InteractiveAuto@using System.ComponentModel.DataAnnotations@using System.Net.Http@using WebAppAutoIndividual.Client.Services@inject ILogger<FormAutoController> Logger@inject ITest2Service Service<PageTitle>Formulaire avec Controleur avec rendu auto</PageTitle><p>Mode de rendu : @(OperatingSystem.IsBrowser() ? "Wasm" : "Server")</p><EditForm Model="Model" OnValidSubmit="SubmitAsync" FormName="StarshipClientAutoRender"><DataAnnotationsValidator /><ValidationSummary /><label> Prénom :<InputText @bind-Value="Model!.FirstName" /></label><label> Nom :<InputText @bind-Value="Model!.Name" /></label><button type="submit">Submit</button></EditForm>@if (allModels == null){<p>Loading ...</p>}else{<label> je suis @serviceName</label><button @onclick="Refresh">Refresh</button> @foreach(DataTest i in allModels) {<p>@i.Name, @i.FirstName</p> }}@code { [SupplyParameterFromForm] public DataTest? Model { get; set; } private DataTest[] allModels { get; set; } = null; private DateTime DateTimeRefresh = DateTime.Now; private string serviceName = "aucun"; protected override async Task OnInitializedAsync() { Model ??= new(); serviceName = Service.Whois(); allModels = await Service.Get(); } protected async Task Refresh() { allModels = await Service.Get(); DateTimeRefresh = DateTime.Now; } private async Task SubmitAsync() { Logger.LogInformation("Prénom Nom = {fisrtname} {name}", Model?.FirstName, Model?.Name); if (Model != null) { await Service.Add(Model); } }}Client side / Service Http
namespace WebAppAutoIndividual.Client.Services;public class Test2ProxyService : ITest2Service{ private readonly HttpClient _http; public Test2ProxyService(HttpClient http) { _http = http; } public string Whois() { return nameof(Test2ProxyService); } public async Task Add(DataTest test) { Console.WriteLine("Service 2 POST depuis le client"); await _http.PostAsJsonAsync("/api/test2", test); } public async Task<DataTest[]> Get() { Console.WriteLine("Service 2 GET test depuis le client"); var result = await _http.GetFromJsonAsync<DataTest[]>("/api/test2"); return result; }}