jack.the.ripper jack.the.ripper - 6 months ago 30
AngularJS Question

AngularJS pass requestVerificationToken to a service

I'd like to pass a RequestVerificationToken which is generated by a Razor MVC helper in my login form to an AngularJS service that I've done to manage the authentication of my application

my form is the following:

<div ng-model="loginRequest" >
<form ng-submit="submit()" ng-controller="loginCtrl">
@Html.AntiForgeryToken()

<input id="username" ng-model="loginRequest.Username" type="text" name="text" />
<input id="password" ng-model="loginRequest.Password" type="text" name="text" />
<input type="submit" id="submit" value="Submit" />
<br/>
isValid: {{loginRequest.isValid}}
<br/>
username: {{loginRequest.Username}}
<br/>
Password: {{loginRequest.Password}}
</form>
</div>


the @Html.AntiForgeryToken() renders in this way:

<input name="__RequestVerificationToken" type="hidden" value="AVzyqDKHSPjaY7L_GTpkasMAABRQRVRFUkFMSUVOV0FSRVxQZWRybwA1">


my AngujarJs controller injects successfully my "loginService" and I can send via Post the username and the password to the service

function loginCtrl($scope, loginService) {
$scope.submit = function () {
loginService.authenticate($scope.loginRequest,function(data) {
$scope.loginRequest.isValid = (data.User!=null);
//console.log(data);
});

};
}


the service:

angular.module('App.services', ['ngResource']).
factory('loginService',
function ($resource) {
return $resource('/Api/User/login', '',
{
authenticate: {
method: 'POST',
isArray: false,
headers: { 'X-XSRF-Token': '?????' }
}
});
});


my question is how can I read the token rendered in the form and pass it to the service and set a header with the token taken from the login form, as far I as Know is not a good practice to manipulate the DOM and I don't know if I'll need to create a directive to perform that task so any suggestions are welcome!

Answer

I think I've found a pretty good solution. I started with the suggestions here http://www.novanet.no/no/blog/olav-nybo/dates/2013/12/anti-forgery-tokens-using-mvc-web-api-and-angularjs/ but the problem was that the directive is executed after the controller. So if you wanted to retrieve initial data in the controller it was very difficult.

Instead of using the directive just use the Module.run() method as referenced in the $http service documentation under the Setting HTTP Headers section http://docs.angularjs.org/api/ng.$http.

I used the HtmlHelper extension referenced in the blog post above with the body element and then my Module.run() looks like this:

myModule.run(['$http', function($http) {
    $http.defaults.headers.common['RequestVerificationToken'] = angular.element("body").attr('ncg-request-verification-token');
}]);

I think it makes for a pretty elegant solution.