0

I am developing an ASP.NET MVC Web Application. I am using AngularJS. But I am having a problem with submitting post form to server because of CSRF validation. First of all, I am new to AngularJS.

In AngularJS, I am submitting form like this on button click event

angular.module('loginApp', ['ui.bootstrap', 'blockUI']).controller('loginController', function ($scope) {

    $scope.loginFormData = { }

    $scope.submitLoginForm = function()
    {
        $http.post("url", $scope.loginFormData, function (response) {

        })
    }
});

At server side, I do CSRF validation to form post

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<JsonResult> Login(LoginViewModel model)
        {
            //Do other stuff
        }

Here is my form HTML:

            @Html.AntiForgeryToken()
            <div class="lock-container">
                <div class="panel panel-default text-center paper-shadow" data-z="0.5">
                    <div class="panel-body">
                        <div class="form-group">
                            <div class="form-control-material">
                                <input class="form-control" ng-model="username" type="text" placeholder="Username">
                                @Html.LabelFor(x => x.UserName)
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="form-control-material">
                                <input class="form-control" ng-model="password" type="password" placeholder="Enter Password">
                                @Html.LabelFor(x=>x.Password)
                            </div>
                        </div>

                        <button ng-click="submitLoginForm()" class="btn btn-primary">Login <i class="fa fa-fw fa-unlock-alt"></i></button>
                    </div>
                </div>
            </div>

Actually it is not a form. I am just submitting data with Ajax basically. You noticed @Html.AntiForgeryToken() at the top. When I inspect in browser, I can see like this.

enter image description here

What I want to do is I want to get that token value and send in the $http post like below.

$http.post("url",{ "_RequestVerificationToken": $scope.csrfToken }, function (response) {

        })

If I send like above, csrf validation will be successful at the server. How can I achieve it it AngularJS?

3 Answers 3

2

In order to csrf validation to be successful at the server, You need to do some modification in your server-side.

you can create a custom filter attribute in your server-side to validate your anti-forgery token.

Create a class and inherited it from ActionFilterAttribute which is provided by System.Web.MVC. Make sure not to use the web API namespaces.

using System;
using System.Web.Helpers;
using System.Web.Mvc;

namespace CustomFilters.Web.Filters
{
    public class MVCAntiForgeryTokenValidatorAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (filterContext.HttpContext.Request.HttpMethod != "GET")
            {
                var header = filterContext.HttpContext.Request.Headers.Get("_RequestVerificationToken");

                var cookieName = AntiForgeryConfig.CookieName; // this also same as the _RequestVerificationToken
                var tokenCookie = filterContext.HttpContext.Request.Cookies.Get(cookieName);

                var tokenHeader = string.Empty;
                if (!string.IsNullOrEmpty(headers))
                {
                    tokenHeader = header;
                }

                AntiForgery.Validate(tokenCookie != null ? tokenCookie.Value : null, tokenHeader);
            }

            base.OnActionExecuting(filterContext);
        }
    }
}

Then you need to modify your method using above created custom attribute

[HttpPost]
[AllowAnonymous]
[MVCAntiForgeryTokenValidator]
public async Task<JsonResult> Login(LoginViewModel model)
{
    //Do other stuff
}

Then you are done. when your method got hit by the angularJs service method, before executing the class method. It will validate the anti-forgery token first.

Sign up to request clarification or add additional context in comments.

Comments

0

You can pass those values in headers instead of the body content. This can be done globally for that module. Refer below links.

angular.module('app')
.run(function ($http) {
$http.defaults.headers.common['X-XSRF-Token'] =
    angular.element('input[name="__RequestVerificationToken"]').attr('value');

});

Please refer this link

AngularJS Web Api AntiForgeryToken CSRF

https://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks

1 Comment

When I add this line, $http.defaults.headers.common['X-XSRF-Token'] = angular.element('input[name="__RequestVerificationToken"]').attr('value'); }); angular js is not working.
0

Add token to FormData

 var formData = new FormData();
    formData.append("__RequestVerificationToken", token);
    formData.append("UserName", $scope.kullaniciAdi);
    formData.append("Password", $scope.sifre);

    $http({
        method: 'POST',
        url: '/Login/Login',
        data: formData,
        transformRequest: angular.identity, 
        headers: { 'Content-Type': undefined }

    }).then(function successCallback(response) {



    }, function errorCallback(response) {

    });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.