This is a migrated thread and some comments may be shown as answers.

Issue with AntiForgeryToken

3 Answers 1102 Views
Data Source
This is a migrated thread and some comments may be shown as answers.
Ryan
Top achievements
Rank 1
Ryan asked on 23 May 2014, 01:39 PM
I'm looking to set up AntiForgeryTokens throughout an application.

This works fine on normal forms (with @Html.AntiForgeryToken() helper), as well as AJAX posts by sending the token value in a cookie. However I have a problem in some cases when trying to send the cookie with requests from Kendo controls.

For example I have the following in a view:

@Html.AntiForgeryToken()
@(Html.Kendo().Grid<UniTech.ICAP.Extranet.Web.Models.ActivityViewModel.ActivityListItem>(Model.ActivityList)
      .Name("Grid")
      .Columns(columns =>
                   {
                       columns.Bound(i => i.UserName);
                       columns.Bound(i => i.ActionString).Filterable(filterable => filterable.UI("actionFilter"));
                       columns.Bound(i => i.ItemString);
                       columns.Bound(i => i.RepositoryString);
                       columns.Bound(i => i.ActionDate).Title("Date").Width(150).Format("{0:dd MMM yyyy HH:mm}");
                   })
      .Sortable()
      .Filterable(filterable => filterable
            .Extra(false)
            .Operators(operators => operators
                    .ForString(str => str.Clear()
                    .StartsWith("Starts with")
                    .IsEqualTo("Is equal to")
                    .IsNotEqualTo("Is not equal to")
                ))
            
      .Resizable(resize => resize.Columns(true))
              .DataSource(datasource => datasource.Ajax().ServerOperation(false).Read(read => read.Action("ActivityGridRead", "Admin")))
              .Pageable(p => p.PageSizes(new[] { 10, 50, 100 }).Enabled(true))
      )

Following from advice in other threads, I have the followin Javascript also on the page:

$(function () {
    var grid = $("#Grid").data("kendoGrid");
    grid.dataSource.transport.options.read.beforeSend = function (req) {
        var header = $('[name=__RequestVerificationToken]').val();
        req.setRequestHeader('__RequestVerificationToken', header);
    };
});

When the page loads, the grid sends a POST to the server to get the activity grid items. There is an attribute that then validates the forgery token:

if (request.IsAjaxRequest())
{
    var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
 
    var cookieValue = antiForgeryCookie != null
        ? antiForgeryCookie.Value
        : null;
 
    AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}

When the request is sent, the validation fails and I cant work out why. This seems to be a problem for any grid that sends a POST to retrieve the data rather than having the data when the page loads.

What I have noticed is that after the first POST fails validation, if I then run the following javascript in firebug console, the validation passes and the grid is populated:

var grid = $("#Grid").data("kendoGrid").dataSource.read();

Any ideas what I'm doing wrong here?

Thanks

3 Answers, 1 is accepted

Sort by
0
Petur Subev
Telerik team
answered on 27 May 2014, 08:41 AM
Hello Ryan,

I assume that this is happening because the option that you set is actually done after the first request is triggered.

There are two options that I could suggest you to try:

1) Set the AutoBind option of the Grid to false and after you set the beforeSend handler trigger the read manually just like you shared

$("#Grid").data("kendoGrid").dataSource.read();


2) Send that antiforgery token the regular way through the Data function of the Read transport.

http://docs.telerik.com/kendo-ui/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/faq#how-do-i-send-values-to-my-action-method-when-binding-the-grid?

Same approach is demonstrated here:

http://www.telerik.com/forums/kendo-grid-antiforgerytoken

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Tejas
Top achievements
Rank 1
answered on 17 Mar 2020, 01:00 PM

I'm looking to set up AntiForgeryTokens throughout an application.

I would like to supply the Token in Header as part of Kendo ComboBox. 

<div class="col-md-6">
<label>Country</label>
@(Html.Kendo().ComboBox()
.Name("cbCountry")
                        .Placeholder("Select")
                        .DataTextField("Name")
                        .DataValueField("CountryId")
                        .Suggest(true)
                        .Filter("contains")
                        .HtmlAttributes(new { @class = "common_select_box" })
                        .Events(e => e.Change("fnReportSelectionDropDownDataBound"))
                        .Value(Convert.ToString(Model.CountryId))
                        .DataSource(source =>
{
                                    source.Read(read =>
                                    {
                                        read.Action("GetCountryList", "Country").Type(HttpVerbs.Post);
                                    });
                                })
                   )
</div>

Adding JavaScript on "Page Load" to find all ComboBox and try to attached Header with Token before Posting comboBox Post request.
$("input").each(function () {
    var cBox = $(this).data("kendoComboBox");
    if (cBox) 
    {
cBox.dataSource.transport.options.read.beforeSend = function (req) {
        var header = $('[name=__RequestVerificationToken]').val();
        req.setRequestHeader('__RequestVerificationToken', header);
        // attach handler to cb
        alert(this.id);
       };
   }
});

 

Can you please help me with this code.

0
Veselin Tsvetanov
Telerik team
answered on 19 Mar 2020, 08:31 AM

Hi Tejas,

The initial Read request send from the ComboBox will be performed straight after the initialization of the widget. Having that said, the $(document).ready(); handler will be executed after the initial Read request has been sent. In order to force the Read after the ready() handler, you should set the AutoBind(false) option of the ComboBox to false. Then, in the loop iterating over the combos, you should call read() on each ComboBox DataSource:

cBox.dataSource.transport.options.read.beforeSend = function (req) {
	var header = "test";
	req.setRequestHeader('__RequestVerificationToken', header);
};

cBox.dataSource.read();

Attached you will find a small sample implementing the above suggestion.

Regards,
Veselin Tsvetanov
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Tags
Data Source
Asked by
Ryan
Top achievements
Rank 1
Answers by
Petur Subev
Telerik team
Tejas
Top achievements
Rank 1
Veselin Tsvetanov
Telerik team
Share this question
or