Cannot post node as authenticated user from phonegap

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
pmunch's picture

Hi all,

I have spent hours trying to figure this out as well as finding relevant code examples, I'm stuck...

I'm building a basic phonegap app that should allow to post a node as authenticated user. I can successfully login, but I cannot further post as this authenticated user thru X-CSRF-Token: I always get 403 - "Access denied for user 001" ...

I summed up the steps I follow in the dummy loginAndPost() function below.

function loginAndPost() {
    
    // Set some vars
    
    var username = "001";
    var password = "001";
    var server_uri = "http://my-drupal-website";
    var services_endpoint = "00";
    
    
    // Step 1 : Get a session token from /services/session/token
    
    var xhr_1 = new XMLHttpRequest(); 
    var xhr_1_url = server_uri+"/services/session/token";
    xhr_1.open('GET', xhr_1_url, false);
    xhr_1.send();
    var xhr_1_token = xhr_1.response;
    console.log(xhr_1_token);
    
    
    // Step 2 : Login using credentials AND session token
    
    var xhr_2 = new XMLHttpRequest(); 
    var xhr_2_url = server_uri + "/" + services_endpoint + "/user/login.json";
    xhr_2.open('POST', xhr_2_url, false);
    xhr_2.setRequestHeader("Content-type", "application/json");
    xhr_2.setRequestHeader('X-CSRF-Token', xhr_1_token);
    xhr_2.data = {
            "username":username,
            "password":password,
        };
    xhr_2.send(JSON.stringify(xhr_2.data));
    var xhr_2_resp = JSON.parse(xhr_2.response);
    console.log(xhr_2_resp);
    
    
    // Setp 3 : Create an article node as authenticated user
    
    var xhr_3 = new XMLHttpRequest(); 
    var xhr_3_url = server_uri + "/" + services_endpoint + "/node.json";
    xhr_3.open('POST', xhr_3_url, false);
    xhr_3.setRequestHeader("Content-type", "application/json");
    xhr_3.setRequestHeader('X-CSRF-Token', xhr_2_resp.token);
    xhr_3.data = {
            "title":"my_title",
            "type":"article",
            "body":{
                "und":[{
                    "value":"This is the body"
                  }]
            },
    }
    xhr_3.send(JSON.stringify(xhr_3.data));
    var xhr_3_resp = JSON.parse(xhr_3.response);
    console.log(xhr_3_resp);
    
}

I'm using drupal 7.22, and services 7.x-3.11.

Any hint someone ?

Many thanks in advance...

Comments

New Token Needed After

tyler.frankenstein's picture

After logging in, you need to get a new CSRF Token to pass along. The token you receive as an anonymous user, will be different than the token used for the same user authenticated.

On a side note, jDrupal and/or DrupalGap will be very helpful here. With jDrupal you can just do:

user_login('name', 'secret', {
    success: function(result) {
      var node = {
        type: 'article',
        title: 'hello',
        body: {
          und: [ { value: 'world' }]
        }
      }; 
      node_save(node, {
          success: function(result_2) {
            alert('created node!');
          }
      });
   }
});

jDrupal takes care of all the token retrieval and other heavy lifting. Then you can use DrupalGap to quickly build mobile/web apps for Drupal (built on top of PhoneGap/Cordova)

Same pb using jDrupal

pmunch's picture

Hi Tyler,

Thanks for your reply.

I knew and have looked to jDrupal and Phonegap, which are both... amazing.
I intend to use phonegap in a next project.
Many thanks for sharing this.

So I tried to achive my authenticated node posting with jDrupal using the code you provided, and I still have the same pb...

I surely have something wrong in my code or environment:

1 / On my drupal (7.22) site:

I have the 2 basic node types :
- Article, with "create article" permission set to anonymous users
- Page, with "create page" permission set to authenticated users

"Access content" permission is set to anonymous users

Test user : username "001" has password "001"

I have the services 7.x-3.11 module activated, and 1 only service called "00":
- Machine-readable name of the endpoint: 00
- Server: REST
- Path to endpoint: 00
- Debug mode enabled: checked
- Session authentication: checked
- Response formatters: json
- Request parsing: application/json, application/x-www-form-urlencoded, multipart/form-data
- Resources: all checked

2 / My PhoneGap App

Basically consists in index.html and test.js

index.html

<!DOCTYPE html>
<html>

    <head>
   
        <meta charset="utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="msapplication-tap-highlight" content="no" />

        <!-- WARNING: for iOS 7, remove the width=device-width and height=device-height attributes. See https://issues.apache.org/jira/browse/CB-4323 -->
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
        <!-- Include meta tag to ensure proper rendering and touch zooming -->
       <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css">
       <link rel="stylesheet" type="text/css" href="css/index.css" />
    
       <script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
      <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>

      <script type="text/javascript" src="js/jdrupal-7.x-1.1.min.js"></script>
       <script type="text/javascript" src="js/test.js"></script>

     <script type="text/javascript">

           // Set the site path (without the trailing slash).
         Drupal.settings.site_path = "http://my_drupal_website";
         
           // Set the Service Resource endpoint path.
         Drupal.settings.endpoint = "00";
    
       </script>

    </head>
   
    <body>

      <div data-role="page" id="page_home">
       
           <div data-role="header"><h1>TEST jDRUPAL</h1></div>      
      
           <div data-role="main" class="ui-content">
                <button onclick="createNode('article');">Create ARTICLE</button>
              <button onclick="createNode('page');">Create PAGE</button>
            </div>
                  
           <div data-role="footer" class="app-footer"></div>                      
          
       </div>

        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
        <script type="text/javascript"> app.initialize(); </script>

    </body>

</html>

test.js

function createNode(nodeType) {

var username = "001";
    var password = "001";
   
   user_login(username, password, {

      success: function(result) {
            console.log("User "+username+" logged in");

       var node = {
           type: nodeType,
            title: 'hello',
          body: {
              und: [ { value: 'world' }]
         }
        };
       
     node_save(node, {
            success: function(result_2) {
                console.log(nodeType+" node created");
             },
             error: function(result_2) {
              console.log(nodeType+" node NOT created");
             },
         });
       
    }
  
   });

}

The results

Each posting makes successful authentication (drupal dblog says "Session opened for 001")

But:
- Article nodes are posted as anonymous users
- Page nodes posting results in "Access denied for anonymous users"

NB: I use PhoneGap Developer App for mobile testing on iOs and Android

Any idea ?
Many thanks in advance ;)