Post data from AngularJS via WebAPI method throws CSRF error

Sasanka Athauda asked on August 20, 2017 15:11

Hi,

I'm using AngularJS within Kentico ASP.NET Web Part (Web Form) and would like to post data to a custom web api method which is setup within Kentico. The angularJS method that posts the data throws the error below. How do I bypass this issue? How do I obtain the Anti Forgery Token from ASP.NET Web Part and pass it to the WEB API call?

Your help on this is much appreciated.

[CsrfException: The CSRF hidden field was missing.]\r\n CMS.Protection.Web.UI.CsrfProtection.OnPostMapRequestHandlerExecute(Object sender, EventArgs eventArgs) +392\r\n CMS.Base.AbstractHandler.CallEventHandler(EventHandler1 h, TArgs e) +100\r\n CMS.Base.AbstractHandler.Raise(String partName, List1 list, TArgs e, Boolean important) +711\r\n CMS.Base.SimpleHandler2.RaiseExecute(TArgs e) +100\r\n CMS.Base.SimpleHandler2.RaiseExecute(TArgs e) +143\r\n CMS.Base.SimpleHandler`2.StartEvent(TArgs e) +217\r\n CMS.Base.ApplicationModule.PostMapRequestHandler(Object sender, EventArgs e) +12\r\n

Cheers, Sasanka

Recent Answers


Brenden Kehren answered on August 20, 2017 15:48

Take a look at this SO post. Essentially it's saying to not use the hidden field type. Drop the use of type="hidden" and value=".." in favor of the angular directives ng-hide="true" and ng-model="..."

0 votesVote for this answer Mark as a Correct answer

Sasanka Athauda answered on August 20, 2017 16:12

Hi Brenden,

Thank you for your quick response.

I'm using the code below to post my form data by calling a WEB API method which is setup within Kentico using AngularJS. When I post the data, it gives me the error "The CSRF hidden field was missing". I believe I somehow need to pass the CSRF token value as part of posting data but I don't know how to do this. Not sure whether this is possible?

var application = angular.module('myLanguageApp', ['ngResource']);

var Introduction = application.factory('Introduction', function ($resource) {
    return $resource('/api/plan/SelfAssessment/Introduction/:id', { id: '@id' });
});

alert(Introduction);

application.controller('PLANPracticeProfileIntroductionController', function ($scope, Introduction) {
    $scope.Data = <%= Data %>;



    $scope.Save = function () {

        $scope.Data.__CMSCsrfToken = $('#__CMSCsrfToken').val();

        alert($scope.Data.__CMSCsrfToken );
        Introduction.save($scope.Data, function (data) {
            alert('successful');
        }, function (error) {
            alert(JSON.stringify(error));
            $scope.errors = JSON.stringify(error);
        });

        alert('here');
    };

    $scope.Next = function () {
        alert('next');
    };
});

Cheers,
Sasanka
0 votesVote for this answer Mark as a Correct answer

Michal Samuhel answered on August 20, 2017 16:52

HI Sasanka,

Token should be part of a page to which data is posted, however token is generated into the hidden field only in response after a page is requested(on request a cookie is generated and stored with user).

By comparing both cookie and token request is validated. However protection should be applied only to pages which inherit from System.Page (all asp pages...).I have to admit I do not fully understand your setup, but I would suggest registering a webApi controller outside of page path and post data directly to controller.

0 votesVote for this answer Mark as a Correct answer

Sasanka Athauda answered on August 21, 2017 05:13

Hi Michal,

Thank again for the quick reply.

I'm developing a web part in Kentico where it has a save button and a next button. When the user presses the save button, it commits the data on the form and stays on the same page. I would like to do this action as an asynch call. So I convert the back-end data object into a JSON object and assign it to Angular $scope and get angular to populate the form.

When the user completes the form and clicks on the Save button, I retrieve the JSON object (which is automatically populated thanks to Angular binding) and post it to a WebAPI method. I used the link below to setup the Web API and when I call the get method it works so the Web API is registered correctly.

https://docs.kentico.com/k82/developing-websites/using-asp-net-web-api-with-kentico

But when I call the post method, I get an the error [CsrfException: The CSRF hidden field was missing]. Since the Web API is not inheriting from System.Page, I'm not sure why it's doing the check in the first place.

So I'm a bit lost as to why this error is happening. It seems to be originating from CMS.Protection.Web.UI.CsrfProtection.OnPostMapRequestHandlerExecute and not sure what is expected there.

Any help on this is much appreciated.

Cheers, Sasanka.

0 votesVote for this answer Mark as a Correct answer

Michal Samuhel answered on August 22, 2017 10:38

Hi Sasanka,

I have met a similar problem recently with cause being one of rewrite rules on the server. You could try to setup network monitoring and check if the request is passed correctly.

Based on the description, I guess that the save button does not actually trigger form submit action in .net, although this should not be subjected to protection or rather it should pass. What is the event URL for this exception?

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.