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

Anti forgery tokens

18 Answers 1318 Views
Data Source
This is a migrated thread and some comments may be shown as answers.
Felipe Casanova
Top achievements
Rank 1
Felipe Casanova asked on 09 May 2012, 12:49 AM
Hi

It's mentioned here, http://www.kendoui.com/forums/ui/upload/rails-anti-forgery-tokens.aspx, that you plan on making forgery tokens work for the next release. Did that happen and does it work in the DataSource? I'm trying to do exactly what is described here http://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken but not sure how I can make that work.

Thanks
Matt 

18 Answers, 1 is accepted

Sort by
0
Alexander Valchev
Telerik team
answered on 11 May 2012, 04:20 PM
Hello Matt,

I am glad to inform you that this functionality is available in the latest official release. You can download it from your account and give it a try.

Greetings,
Alexander Valchev
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Felipe Casanova
Top achievements
Rank 1
answered on 11 May 2012, 04:22 PM
Can you clarify how to use it in the datasource please as I can't find any documentation?
0
Accepted
Daniel
Telerik team
answered on 15 May 2012, 01:50 PM
Hello Matt,

I am sorry for the confusion we created. Are you using Rails or ASP.NET MVC?
If you use the jquery-rails gem, such modification is not needed, and the datasource works out of the box (as it uses jQuery ajax).  
If you are using MVC, you could add the token to the request either through the request options:

transport: {
    read: {
        url: url,
        type: "POST",
        data: {
            __RequestVerificationToken: $("input[name=__RequestVerificationToken]").val()
        }
    }

or through the transport parameterMap function. I attached a sample project which implements this scenario. I hope it helps.

Greetings,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Felipe Casanova
Top achievements
Rank 1
answered on 15 May 2012, 09:12 PM
Thanks, very helpful....I should have mentioned MVC.
0
Ed
Top achievements
Rank 1
answered on 19 May 2012, 06:43 AM
This great...very informative..thanks....
0
Michael
Top achievements
Rank 1
answered on 26 May 2012, 03:33 AM
Hmm, the problem becomes when you submit via ajax AND with a json payload. ASP MVC is hardcoded to look for the token in the form-value collection, which nothing is in there of course when using json types.

There is a workaround for this in ASP MVC which requires extending the anti-forgery token class in MVC. But to avoid having to take apart the json package twice to get this value out, I am trying to send it in the headers instead (and then have my custom anti-forgery class look for it there).

The problem is I don't seem to see the header being submitted when the DataSource does its sync. For example: 
update: {
url: 'www.fakeurl.com/blah',
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
headers: { 'Forgery-Token': $("input[name=__RequestVerificationToken]").val()  }
}
Of course, no docs on using the headers but I thought I got that right from another thread. Close? Not close? Any insights why the header isnt being passed?

Thanks!
Mike
0
Michael
Top achievements
Rank 1
answered on 29 May 2012, 06:21 PM
So no response?? As far as I am concerned, this is still a major issue for ASP MVC devs, since many are posting using the json content type and the Forms collection is not populated if so, which is where MVC is hardcoded to look for this token. 

All I have seen in the docs/examples (if I remember right) is a statement that the transport operations is just a thin wrapper over the jQuery AJAX call. And many of the config properties match verbatim (and are truly just passed thru). 

So my question is, is that true for all the allowed $.ajax parameters, including headers? If so, why does my code above not send the declared header? If it is not supported, is there a recommendation for adding a header to these update operations on the transport?

Thanks!
Mike
0
Daniel
Telerik team
answered on 30 May 2012, 04:17 PM
Hello Mike,

Yes, all jQuery Ajax parameters can be used in the configuration and at least on my side the headers are send with the request. Is the "Forgery" header sent when using a normal request outside of the DataSource? Also, please check if it is sent when using the beforeSend event to add it e.g.

update: {
    url: url,
    type: "POST",
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    beforeSend: function (xhr) {
        xhr.setRequestHeader('Forgery-Token', $("input[name=__RequestVerificationToken]").val());
    }
}

Regards,
Daniel
the Telerik team
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
0
Michael
Top achievements
Rank 1
answered on 30 May 2012, 06:35 PM
I am an idiot. Longer story shorter, my pages are built dynamically. In the case with the lists (grids), there wasn't a token being created and sent to the client in the first place. That is why it wasn't being sent. :)

For posterity, I can confirm that both methods work (using headers like I was and your example of using the beforeSend event).

Thank you for confirming all ajax options are supported!

Cheers,
Mike
0
Matthew
Top achievements
Rank 1
answered on 01 Apr 2015, 05:41 PM
I am using MVC and the @(Html.Kendo().Grid... syntax with .DataSource(..Server() binding.  Do you all plan to make the __RequestVerificationToken auto handled with this syntax?  Or is there a way to add the parameterMap with this syntax?
0
Daniel
Telerik team
answered on 07 Apr 2015, 07:39 AM
Hello,

Adding the token automatically is not planned and a parameterMap function is not available because the requests are made via HTML elements in this mode. It should be possible to pass the token when using server binding by adding it to the route values:
@{
    var token = Html.AntiForgeryToken().ToHtmlString();
    var tokenValue = new System.Text.RegularExpressions.Regex("value=\"(.*?)\"").Match(token).Groups[1].Value;
    var routeValues = new { __RequestVerificationToken = tokenValue };
}
@(Html.Kendo().Grid(Model)
    .Name("grid")
    .DataSource(dataSource => dataSource
        .Server()       
        .Read(read => read.Action("ReadAction", "Controller", routeValues))
        .Update(update => update.Action("UpdateAction", "Controller", routeValues))
        .Create(create => create.Action("CreateAction", "Controller", routeValues))
        .Destroy(destroy => destroy.Action("DestroyAction", "Controller", routeValues))

For update and create you could also include the token inside an editor used for the grid. 

Regards,
Daniel
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Matthew
Top achievements
Rank 1
answered on 08 Apr 2015, 05:49 PM
I am not sure how to make MVC use the new routeValues in the controllers.  Can you provide a sample for that as well?
0
Atanas Korchev
Telerik team
answered on 13 Apr 2015, 10:35 AM

Hello Matthew,

You shouldn't  need to do anything else as long as those routeValues are used in the DataSource configuration.

The grid will send them as part of the request.

Read(read => read.Action("ReadAction""Controller", routeValues))
        .Update(update => update.Action("UpdateAction""Controller", routeValues))
        .Create(create => create.Action("CreateAction""Controller", routeValues))
        .Destroy(destroy => destroy.Action("DestroyAction""Controller", routeValues))

 

What happens when you do that?

Regards,
Atanas Korchev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Brad
Top achievements
Rank 1
answered on 27 May 2016, 08:35 PM
I've been trying to do this exact thing for a few days with no success.  Here's the DataSource configuration for my server bound mvc grid:

.DataSource(dataSource => dataSource
.Server()
.Destroy(x => x.Action("Delete", "ControllerName", routeValues))
.Model(model => {model.Id(r => r.Id);}))

 

The delete button posts and adds the request verification token to the route value as expected, but I get the following error: The required anti-forgery form field "__RequestVerificationToken" is not present.

After looking at the resulting HTML I now realize that the anti forgery token must be included withing the <form> that surrounds the delete button for it to work properly.  Is there any way to accomplish this?

Thanks!

0
Brad
Top achievements
Rank 1
answered on 27 May 2016, 09:08 PM

I had an epiphany of sorts right after making my previous post that I thought I should share.  I discovered a way to add an antiforgerytoken to each form within the grid row.  Here's the column code:

columns.Command(command => {
command.Destroy().Text(Html.AntiForgeryToken().ToHtmlString() + "Delete");})

This is not a pretty solution, but it does the trick.  Also, if you don't want lots of different AntiForgeryTokens running around in your grid here's another method:

@{ string antiForgeryTokenText = Html.AntiForgeryToken().ToHtmlString();}
 
// Inside your grid column
columns.Command(command => {
     command.Destroy().Text(antiForgeryTokenText + "Delete");
})

This eliminates repeated calls to Html.AntiForgeryToken helper, which I like.

It would be nice if there were another more specialized method besides Text() to do this, perhaps something like this: .FormHiddenValues(new {AdditionalFormValue="some value"}). 

I would still like to see some method of automatically adding the antiforgerytoken in the future for both server and ajax bound grids.

Thanks!

0
Chris
Top achievements
Rank 1
answered on 07 Apr 2017, 12:21 PM
This doesn't work because the token is appended to the querystring rather than as a form post value. Any other ideas?
0
Viktor Tachev
Telerik team
answered on 12 Apr 2017, 11:16 AM
Hello Chris,

Please ensure that you use the server binding configuration for DataSource suggested in the previous posts. 

Alternatively, you can pass the additional information via the Data() function of the Read Action as described in the thread below:



Regards,
Viktor Tachev
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Chris
Top achievements
Rank 1
answered on 17 Apr 2017, 09:35 AM

Thanks Victor, I managed to get this working with .Data().

For anyone else struggling with this, this is how I got it working:

@(Html.Kendo().Grid<TestViewModel>()
    .DataSource(dataSource => dataSource
        .Ajax()
        .Create(cfg => cfg
            .Action("Create", "Test")
            .Data("getRequestVerificationToken")
        )
        .Update(cfg => cfg
            .Action("Update", "Test")
            .Data("getRequestVerificationToken")
        )
    )
)

 

With the javascript function as follows:

function getRequestVerificationToken() {
    return {
        __RequestVerificationToken: "@(new System.Text.RegularExpressions.Regex("value=\"(.*?)\"").Match(Html.AntiForgeryToken().ToHtmlString()).Groups[1].Value)"
    };
}
Tags
Data Source
Asked by
Felipe Casanova
Top achievements
Rank 1
Answers by
Alexander Valchev
Telerik team
Felipe Casanova
Top achievements
Rank 1
Daniel
Telerik team
Ed
Top achievements
Rank 1
Michael
Top achievements
Rank 1
Matthew
Top achievements
Rank 1
Atanas Korchev
Telerik team
Brad
Top achievements
Rank 1
Chris
Top achievements
Rank 1
Viktor Tachev
Telerik team
Share this question
or