signalpoint / angular-drupal

An Angular JS module for Drupal.
GNU General Public License v2.0
116 stars 33 forks source link

Login failing #2

Open HaroldRKnieriem opened 9 years ago

HaroldRKnieriem commented 9 years ago

When I try to login to the Drupal site the login is failing. Any help would be appreciated.

FYI: I added console.log statements in the user_login and connect functions. Here is the output:

_userlogin():

config: Object
  data: Object
    password: "test1234"
    username: "testuser"

data: Object
  sessid: "tfH2bdGIwCBD4ozoPaQn06mEanYZpD6rZfW8hTKPgT0"
  session_name: "SESSbf88127597425f6389f62f338f0cc5d5"
  token: "d23PmNvcjVkzioxspZLTBx2WNaju0wmTOl0d0oFYWfo"
  user: Object
    access: "0"
    created: "1435764274"
    data: false
    language: ""
    login: 1435764297
    mail: "***@******.***"
    name: "testuser"
    picture: null
    rdf_mapping: Object
    roles: Object
      2: "authenticated user"
    __proto__: Object
    signature: ""
    signature_format: "filtered_html"
    status: "1"
    theme: ""
   timezone: "America/New_York"
   uid: "14"

connect():

config: Object
  headers: Object
    Accept: "application/json, text/plain, */*"
    X-CSRF-Token: "d23PmNvcjVkzioxspZLTBx2WNaju0wmTOl0d0oFYWfo"

data: Object
  sessid: "tfH2bdGIwCBD4ozoPaQn06mEanYZpD6rZfW8hTKPgT0"
  session_name: "SESSbf88127597425f6389f62f338f0cc5d5"
  user: Object
    cache: 0
    hostname: "::1"
    roles: Object
      1: "anonymous user"
    __proto__: Object
    timestamp: 1435764298
    uid: 0

Drupal Module: Services: 7.x-3.12

signalpoint commented 9 years ago

@HaroldRKnieriem please use GitHub Markdown when posting issues/comments. I've updated the issue to include some basic markdown to help wrap the json output.

As for the issue(s), from the output above, it looks like the login call correctly logs in, since user # 14 is coming back in the response data.

It appears it is the subsequent connect call (processed automatically after logging in) that is reporting the user as anonymous.

Are you developing your app in the same domain as the Website? i.e.

// drupal site lives here
www.example.com

 // app lives here
www.example.com/mobile-application
HaroldRKnieriem commented 9 years ago

@signalpoint Thank you for you quick response, and I apologize for the lack of Markdown. This is my first GitHub issue.

They are both on the same domain, currently:

// app lives at
http://lp-sales.home.dev/

// drupal lives at
http://lp-sales.home.dev/services

I also noticed that with both sites in the same browser (different tabs) that logging in via the app does correctly log me in on the Drupal site tab, so the process is working. I did find this article https://www.drupal.org/node/2342105, but it looks as though the connect function does have the CSRF-Token in the header.

signalpoint commented 9 years ago

@HaroldRKnieriem thank you for clarifying. Will you please share some sample code of your usage of drupal.user_login()?

HaroldRKnieriem commented 9 years ago

@signalpoint Here's the start of my app.js.

(function() {
  var app = angular.module("salessheet", ['angular-drupal']);

  app.run(['drupal', function (drupal) {

    drupal.user_login('admin_hfa', 'Pass1234').then(function (data) {
      if (data.user.uid) {
        alert('Hello ' + data.user.name + '!');
        drupal.node_load(1).then(function (node) {
          alert(node.title);
        });
      }
      else {
        alert("failed login");
      }
    });

  }]);

// The angular-drupal configuration settings for my simple app.
  angular.module('angular-drupal').config(function($provide) {

    $provide.value('drupalSettings', {
      sitePath: 'http://lp-sales.home.dev/services',
      endpoint: 'api'
    });

  });
...
signalpoint commented 9 years ago

@HaroldRKnieriem Just to confirm... and then the data.user.uid always comes back as zero?

HaroldRKnieriem commented 9 years ago

@signalpoint Yes. The connect function returns data.user.uid as 0 and the data.user.rules object comes back as 'anonymous user'.

signalpoint commented 9 years ago

@HaroldRKnieriem that is strange, I'm not sure why that is happening. What if you copy/paste the code that powers the user login (so you can make your own manual call), and then in its then callback make a to system connect with your own manual call. What happens then? I'm curious if even without angular-drupal, if it will work or not in your environment.

cgranville commented 9 years ago

@signalpoint I've run into the same issue as well.

signalpoint commented 9 years ago

@cgranville will you please describe your development environment? i.e. localhost vs remote, application (web, mobile) vs headlesss, any cross domain issues, CORS policy.

For me personally, I've used it with the environment described here: http://tylerfrankenstein.com/code/headless-drupal-angular-js-bootstrap

In order to properly resolve this, we should learn as much as we can about the different environments, and how we can have this module operate properly.

cgranville commented 9 years ago

@signalpoint Environment: Angular appLocalhost:2000, Drupal: localhost: 8083 Allow-Origin: * Allow-Headers: Origin, Content-Type, Accept, X-CSRF-Token, Authorization, Token Allow-Methods: PUT, GET, POST, DELETE, OPTIONS

signalpoint commented 9 years ago

@cgranville I suppose the * should allow the communication between 2000 and 8083, but that's a realm of skills I'll defer to your judgement on. Have you tried launching e.g. Chrome with security disabled?

On a side note, I am still a n00b with Angular, but I recall there being a way to launch an app via the terminal (i.e. not just navigating to a URL in the browser). It's possible that while launching an app in the aforementioned way, results in cookies not being set properly in the app's browser, and may result in this anonymous behavior.

signalpoint commented 9 years ago

After a bit more research, it appears running the app and Drupal on the same port is a good idea if you want to avoid potential CORS issues. This way the cookie should be set properly, and the authentication should hold across page visits.

openbook commented 9 years ago

I'm using this on a subdomain (using http-server & proxypass in the apache config) and initially got the same login issue - the session is created but the browser wouldn't store/use the cookie when making subsequent requests & returned an anonymous user error.

I was able to get round this by adding the 'withCredentials' header to all requests:

angular.module("angular-drupal").config(['$httpProvider',
  function($httpProvider) {
    $httpProvider.interceptors.push(['$q',
      function($q) {
        return {
          request: function(config) {
            config.withCredentials = true;
            return config;
          }
        };
      }
    ]);
  }
]);

and also setting "Access-Control-Allow-Credentials" "true" in the apache config.

signalpoint commented 9 years ago

@openbook Thank you for the detailed explanation of the way around the issue, much appreciated!

thomas7373 commented 9 years ago

I think you should use the token got from user/login post, don't make a session/token get after it, because if you don't have the cookie set, that will return a new, anonymous session token. Plus one spare http request less.

signalpoint commented 9 years ago

@thomas7373 thank you for pointing this out. It wasn't always this way, Services used to not include the token in the result of the user login call. I'll create a separate issue for this to have the extra call removed from the login success.

sickpalmex commented 9 years ago

@openbook Thank you very much , I spent hours trying to resolve annonymus user login and your fix solved my problem

webdobe commented 8 years ago

I ended up adding this to my a drupal module that also has additional services. Might not be 100% (Not sure I like the use of current_path();) but seems to allow me to configure origins that can connect to my services with an angular app. I have a admin page that I can configure origins. Since you can only have 1 origin at a time I'm doing a check to make sure the server origin is from one that I set.

function mymodule_init() {
    $paths = explode('/', current_path());
    if ($paths[0] == 'api' || $paths[0] == 'services') {
        $origin = $_SERVER['HTTP_ORIGIN'];
        $origins = explode(',', preg_replace('/\s+/', '', variable_get('mymodule_allowed_origins', '')));
        if (in_array($origin, $origins)) {
            drupal_add_http_header('Access-Control-Allow-Origin', $origin);
            drupal_add_http_header('Access-Control-Allow-Credentials', 'true');
            drupal_add_http_header('Access-Control-Allow-Headers', 'Content-Type, X-CSRF-Token');
        }
    }
}
Saneesh commented 8 years ago

@openbook , @signalpoint I'm developing a mobile app using the seed https://github.com/mario-aleo/cordova-angular-angularMaterial-seed. To interact with Drupal services I'm using https://github.com/easystreet3/angular-drupal.

  1. My Drupal installation is another server.
  2. Using the command cordova serve I'm running my cordova app in localhost.

The issue is, when I login Drupal returns the user as anonymous. As you said I tried withCredentials but still I'm getting the uid as zero.

In the cosole we can see like, when submit to user/login.json, it successfully logged in and can see a token. then it calls the URL service/session/token which returns a different token. then it calls system/connect.json which shows the uid=0 (anonymous user)

app.js

/**
 * @file
 * Main app.
 */

"use strict";

/*jslint browser: true, unparam: true */
var myApp = angular.module("ngapp", [ "ui.router", "ngMaterial", "ngCookies", "ngMessages", "ngCordova", "ngStorage", "revolunet.stepper", "angular-drupal" ])
  // The ngTouch is No Longer Supported by Angular-Material.
  .run(['$rootScope', '$cordovaDevice', '$cordovaStatusbar', '$log', '$http', '$location', '$localStorage', function ($rootScope, $cordovaDevice, $cordovaStatusbar, $log, $http, $location, $localStorage) {
    $log.debug("App running...");

    // Status bar related.
    document.addEventListener("deviceready", function () {
      // Always Show Status Bar.
      $cordovaStatusbar.overlaysWebView(false);

      // Status Bar With Green Color, Using Angular-Material Style.
      $cordovaStatusbar.styleHex('#2A771B');

      if (window.plugins && window.plugins.orientationLock) {
        window.plugins.orientationLock.lock("portrait");
      }
    }, false);
    /* Hijack Android Back Button (You Can Set Different Functions for Each View by Checking the $state.current)
    document.addEventListener("backbutton", function (e) {
        if($state.is('init')){
          navigator.app.exitApp();
        }  else{
          e.preventDefault();
        }
      }, false);*/
  }])

  // Angular-Material Color Theming.
  .config(function ($mdThemingProvider, $mdGestureProvider) {
    $mdGestureProvider.skipClickHijack();

    $mdThemingProvider.theme('default')
      .primaryPalette('green')
      .accentPalette('light-green');
  })

  // Angular Drupal Configuration Settings.
  .config(['$provide', function ($provide) {
    $provide.value('drupalSettings', {
      sitePath: 'http://demo.drupal.backend/',
      endpoint: 'api/v1'
    });
  }])

  // CORS issue fix.
  .config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push(['$q',
      function ($q) {
        return {
          request: function (config) {
            config.withCredentials = true;
            return config;
          }
        };
      }
      ]);
  }]);

LoginController

"use strict";
/*global kiranaApp */
/*jslint unparam: true, white:true, devel: true  */
myApp.controller('LoginController', ['$scope', '$location', 'drupal', function($scope, $location, drupal) {
  var vm = this;

  function test_login () {
    drupal.user_login("Admin", "Admin@123").then(function(data) {
      console.log(data);
      alert('Hello world and hello ' + data.user.name + '!');
    });
  }

  vm.login = function() {
    test_login();    
  };
}]);

I'm testing the app in Chrome/Firefox by disable the disable-web-security and enable CORS plugins. I don't know these kind of setting will affect when I build the .apk. :-)

Do you have any thoughts about why the user is logged in as anonymous? Is there any other settings I'm missing in Drupal/AngularJS side?