Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling CSRF/XSRF tokens with Angular frontend and Drupal 7 backend

I'm in the process of building a new AngularJS frontend for a Drupal 7 website. This is using the Services module with session-based authentication, across two domains using CORS. I am able to authenticate with Drupal, retrieve the user object and session data, and then get the CSRF token from the services module. What I'm having trouble with is setting all this up in the header so that subsequent requests are authenticated. I understand the overall concept but am new to both AngularJS and preventing CSRF attacks.

From what I have gathered reading about this set-up with AngularJS and RubyOnRails, there can be inconsistencies between platforms concerning what the token is named and how it is processed. There also seems to be a number of suggestions on how to set this token in the header. However, I'm having trouble in finding a solid example of how to get these platforms speaking the same language.

The only thing I'm doing with my $httpProvider in app.js is:

delete $httpProvider.defaults.headers.common['X-Requested-With'];

The login controller, in controller.js:

  .controller('LoginCtrl', ['$scope', '$http', '$cookies', 'SessionService', function($scope, $http, $cookies, SessionService) {
    $scope.login = function(user) {
        //set login url and variables
        var url = 'http://mywebsite.com/service/default/user/login.json';
        var postDataString = 'name=' + encodeURIComponent(user.username) + '&pass=' + encodeURIComponent(user.password);

        $http({
            method: 'POST',
            url: url,
            data : postDataString,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        }).success(function (data, status, headers, config) {
            var sessId = data.sessid;
            var sessName = data.session_name;
            $cookies[sessName] = sessId;

            var xsrfUrl = 'http://mywebsite.com/services/session/token';
            $http({
                method: 'GET',
                url: xsrfUrl
            }).success(function (data, status, headers, config) {
                $cookies["XSRF-TOKEN"] = data;
                SessionService.setUserAuthenticated(true);
            }).error(function (data, status, headers, config) {
                console.log('error loading xsrf/csrf');
            });
        }).error(function (data, status, headers, config) {
            if(data) {
                console.log(data);
                var msgText = data.join("\n");
                alert(msgText);
            } else {
                alert('Unable to login');
            }
        });
      };
like image 857
RevNoah Avatar asked Mar 23 '23 23:03

RevNoah


2 Answers

The solution has to do with how the cookies need to be set and then passed through subsequent requests. Attempts to set them manually did not go well but the solution was simpler than I expected. Each $http call needs to set the options:

withCredentials: true

Another change I made was to use the term CSRF instead of XSRF, to be consistent with Drupal. I didn't use any built-in AngularJS CSRF functionality.

like image 189
RevNoah Avatar answered Apr 06 '23 12:04

RevNoah


        addItem: function(data)
        {
            return $http.post('api/programs/'+$stateParams.id+'/workouts', {item:data},{
                headers:
                {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                    'X-CSRF-Token': $('meta[name="xxtkn"]').attr('content')

                }
            });
        }

since it has been a year of this topic! not sure still encountering the same problem but for the ones who comes to search for answers here is how i handle it! Pay attention the headers{} part i define a new header and call it X-CSRF-Token and grab value from the DOM of (serverside) generated html or php. It is not a good practise to also request the csrf token from the server.Cuz attacker could somehow request that as well. Since you save it as a cookie. Attacker can steal the cookie! No need to save it in a cookie! send the token with header and read it in the serverside to match it!

and for multitab of a same page issue. I use the same token thruout the whole session. Only regenerate on login, logout and change of major site or user settings.

like image 25
Oguzhan Avatar answered Apr 06 '23 12:04

Oguzhan