Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
db65b16
docs(upload): Add KB for Antiforgery integration
dimodi Jan 16, 2024
027c69d
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
a6d1723
Update components/upload/troubleshooting.md
dimodi Jan 16, 2024
ea49ce3
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
210b6a6
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
5ade126
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
edead98
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
fc1bcb4
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
a3b1e41
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
e838aed
Update components/upload/events.md
dimodi Jan 16, 2024
7d5433a
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
285cf10
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
76cc99f
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
32ac1d6
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
7a6d8f8
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
8a7e536
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
64fbfa6
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
0617eac
Update knowledge-base/upload-validateantiforgerytoken.md
dimodi Jan 16, 2024
d83070a
improve bullet point
dimodi Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/upload/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ If you cancel the event, the file upload will not start. If `AutoUpload="false"`
Use the `OnUpload` and [`OnRemove`](#onremove) event handlers to send additional custom data and request headers to the server, together with the file. For example, the data may be related to:

* Authentication
* CSRF cross-site anti forgery tokens
* [CSRF/XSRF cross-site antiforgery tokens]({%slug upload-kb-validateantiforgerytoken%})
* Any metadata related to the app business logic

To send **cookies** with the upload request, set the [`WithCredentials` component parameter]({%slug upload-overview%}#upload-parameters) to `true`.
Expand Down
5 changes: 5 additions & 0 deletions components/upload/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ The server does not return any response. The browser console shows connection er
This means that the uploaded file size [exceeds the web server's maximum]({%slug upload-overview%}#large-file-uploads).


## Antiforgery Validation Blocks the Upload Requests

If the upload controller is decorated with the `[ValidateAntiForgeryToken]` attribute, the Upload component must include antiforgery tokens in its upload and delete requests. Use the [`OnUpload` and `OnRemove`]({%slug upload-events%}) events to [add the required antiforgery tokens]({%slug upload-kb-validateantiforgerytoken%}).


## See Also

* [How to implement Upload controller methods]({%slug upload-overview%}#implement-controller-methods)
Expand Down
229 changes: 229 additions & 0 deletions knowledge-base/upload-validateantiforgerytoken.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
---
title: Upload Files with Antiforgery Validation
description: Learn how to setup the Telerik Blazor Upload to work with .NET controllers that use the ValidateAntiForgeryToken attribute. Configure Blazor apps with antiforgery validation.
type: how-to
page_title: How to Upload Files with Antiforgery Validation
slug: upload-kb-validateantiforgerytoken
position:
tags: telerik, blazor, upload
ticketid: 1626509, 1637325
res_type: kb
---

## Environment

<table>
<tbody>
<tr>
<td>Product</td>
<td>Upload for Blazor</td>
</tr>
</tbody>
</table>


## Description

This KB article answers the following questions:

* How to use the Telerik Blazor Upload component with controllers that are decorated with the `[ValidateAntiForgeryToken]` attribute?
* How to upload files to controllers that require antiforgery validation?
* How to set antiforgery tokens in the Upload's `OnUpload` and `OnRemove` events?


## Solution

Here are the suggested steps to configure .NET Core Blazor antiforgery validation and integrate it with the Telerik Upload component.

1. Add services and configurations to `Program.cs`:
* Add `builder.Services.AddRazorPages();`
* Add `builder.Services.AddHttpContextAccessor();`
* (optional) Add `builder.Services.AddAntiforgery()` with custom `HeaderName` or `FormFieldName`.
* Verify that `app.UseAntiforgery();` is present.
* Add `app.MapDefaultControllerRoute();` to configure routing.
1. [Implement the `Save` and `Remove` controller methods]({%slug upload-overview%}#implement-controller-methods).
1. Decorate the controller class or specific action methods with `[ValidateAntiForgeryToken]`
1. Configure the Razor component, which contains the Telerik Blazor Upload:
* Inject `AntiforgeryStateProvider` to use its `GetAntiforgeryToken()` method.
* Inject `IAntiforgery` to use its `GetAndStoreTokens(httpContext)` method.
* Inject `IHttpContextAccessor` to use its `HttpContext` property in the `GetAndStoreTokens()` method.
* Execute `GetAndStoreTokens()` and/or `GetAntiforgeryToken()` in `OnInitialized` to obtain the required antiforgery information.
* Add the required antiforgery information in the Upload component's [`OnUpload` and `OnRemove` event handlers]({%slug upload-events%}).

The code snippets below assume that the application name is `BlazorAppName`.

>caption Using Telerik Blazor Upload with antiforgery validation

<div class="skip-repl"></div>

````Program.cs
// This is not the complete Program.cs file, but only the relevant bits.

using Microsoft.AspNetCore.Http.Features;
// Required by ValidateAntiForgeryTokenAttribute()
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

// ...

// Required by MapDefaultControllerRoute()
builder.Services.AddRazorPages();

// Not necessary due to AddRazorPages()
//builder.Services.AddControllersWithViews(options =>
//{
// options.Filters.Add(new ValidateAntiForgeryTokenAttribute());
//});

// Required by Antiforgery.GetAndStoreTokens() in Razor components
builder.Services.AddHttpContextAccessor();

// This statement and the custom names are optional.
builder.Services.AddAntiforgery(options => {
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.FormFieldName = "X-CSRF-TOKEN-FORMFIELDNAME";
});

builder.Services.AddTelerikBlazor();

// ASP.NET Core Upload file size limit
builder.Services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 4_294_967_296; // 4 GB
});
// Kestrel Upload file size limit
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.Limits.MaxRequestBodySize = 4_294_967_296; // 4 GB
});

var app = builder.Build();

// ...

app.UseAntiforgery();

// Requires AddRazorPages() or AddControllersWithViews()
app.MapDefaultControllerRoute();

// ...

app.Run();
````
````Razor
@using Microsoft.AspNetCore.Antiforgery

@inject AntiforgeryStateProvider AfStateProvider
@inject IAntiforgery Antiforgery
@inject IHttpContextAccessor HttpContextAccessor
@inject NavigationManager NavigationManager

<PageTitle>Home</PageTitle>

<TelerikUpload SaveUrl="@UploadSaveUrl"
RemoveUrl="@UploadRemoveUrl"
OnUpload="@OnUploadUpload"
OnRemove="@OnUploadRemove" />

@code {
private string UploadSaveUrl => ToAbsoluteUrl("api/upload/save");
private string UploadRemoveUrl => ToAbsoluteUrl("api/upload/remove");

private string? AntiforgeryHeaderName { get; set; }
private string? AntiforgeryHeaderToken { get; set; }
private string? AntiforgeryFormFieldName { get; set; }
private string? AntiforgeryFormValue { get; set; }

private void OnUploadUpload(UploadEventArgs args)
{
// There is no need to post both antiforgery header and data.
// Only one of them is enough.

args.RequestHeaders.Add(AntiforgeryHeaderName, AntiforgeryHeaderToken);
args.RequestData.Add(AntiforgeryFormFieldName, AntiforgeryFormValue);
}

private void OnUploadRemove(UploadEventArgs args)
{
// There is no need to post both antiforgery header and data.
// Only one of them is enough.

args.RequestHeaders.Add(AntiforgeryHeaderName, AntiforgeryHeaderToken);
args.RequestData.Add(AntiforgeryFormFieldName, AntiforgeryFormValue);
}

protected override void OnInitialized()
{
// Obtain the antiforgery header name and value.
if (HttpContextAccessor.HttpContext != null)
{
var afTokenSet = Antiforgery.GetAndStoreTokens(HttpContextAccessor.HttpContext);
AntiforgeryHeaderName = afTokenSet.HeaderName;
AntiforgeryHeaderToken = afTokenSet.RequestToken;
}

// Obtain the antiforgery form field name and value.
var afRequestToken = AfStateProvider.GetAntiforgeryToken();
if (afRequestToken != null)
{
AntiforgeryFormFieldName = afRequestToken.FormFieldName;
AntiforgeryFormValue = afRequestToken.Value;
}

base.OnInitialized();
}

private string ToAbsoluteUrl(string url)
{
return $"{NavigationManager.BaseUri}{url}";
}
}
````
````Controller
using Microsoft.AspNetCore.Mvc;

namespace BlazorAppName.Controllers
{
[ValidateAntiForgeryToken]
[Route("api/[controller]/[action]")]
public class UploadController : ControllerBase
{
public IWebHostEnvironment HostingEnvironment { get; set; }

public UploadController(IWebHostEnvironment hostingEnvironment)
{
HostingEnvironment = hostingEnvironment;
}

[HttpPost]
public async Task<IActionResult> Save(IFormFile files)
{
// Save the file...

return new EmptyResult();
}

[HttpPost]
public async Task<IActionResult> Remove([FromForm] string files)
{
// Delete the file...

return new EmptyResult();
}
}
}
````


## Disclaimer

> This article contains code snippets and suggestions that relate to general .NET programming and antiforgery setup of a Blazor application. The provided implementation is just an example and is strictly outside the Telerik support scope. The primary resource for antiforgery configuration is the Microsoft documentation. See [Blazor authentication and authorization](https://learn.microsoft.com/en-us/aspnet/core/blazor/security/).


## See Also

* [Upload Overview]({%slug upload-overview%})
* [Upload Events]({%slug upload-events%})
* [Upload Troubleshooting]({%slug upload-troubleshooting%})