I've been playing about with the Deploy module and noticed a issue. Using the DeployAuthenticatorSession implementation it successfully authenticates with a remote instance but when it tries to post a node it receives a 401 response code.

Tracking this down it looks to be because on successful login the session cookie is retrieved from the 'set-cookie' header.

Doing a curl this looks something like the below:

$ curl -i -H "Content-Type: application/json"  -X POST -d '{"username":"admin","password":"changeme"}' http://sandbox/services/rest/user/login

HTTP/1.1 200 OK
Date: Wed, 21 Mar 2012 13:24:36 GMT
Server: Apache
X-Powered-By: PHP/5.3.9-ZS5.6.0 ZendServer/5.0
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Wed, 21 Mar 2012 13:24:36 GMT
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
ETag: "1332336276"
Vary: Accept
Content-Length: 115
Content-Type: text/yaml
Set-Cookie: ZDEDebuggerPresent=php,phtml,php3; path=/
Set-Cookie: SESSb50fde67a9f8d9abe7f9631416b7fd2e=gREQTXYr7h0-wrqiHoVcu7QexUmOfmvCXutHY2fxyKo; expires=Fri, 13-Apr-2012 16:57:56 GMT; path=/; domain=.sandbox; HttpOnly

---
sessid: gREQTXYr7h0-wrqiHoVcu7QexUmOfmvCXutHY2fxyKo
session_name: SESSb50fde67a9f8d9abe7f9631416b7fd2e
user: |

drupal_http_request takes the 'set-cookie' header and then stores it as :

ZDEDebuggerPresent=php,phtml,php3; path=/,SESSb50fde67a9f8d9abe7f9631416b7fd2e=gREQTXYr7h0-wrqiHoVcu7QexUmOfmvCXutHY2fxyKo; expires=Fri, 13-Apr-2012 15:40:01 GMT; path=/; domain=.sandbox; HttpOnly

This means we set the above value when the below is used in DeployAuthenticatorSession.inc which is a invalid cookie. The value is invalid? It should be : "SESSb50fde67a9f8d9abe7f9631416b7fd2e=gREQTXYr7h0-wrqiHoVcu7QexUmOfmvCXutHY2fxyKo; expires=Fri, 13-Apr-2012 15:40:01 GMT; path=/; domain=.sandbox; HttpOnly"

      if (!empty($response->headers['set-cookie'])) {
        // Set the session cookie, retrieved from the login request on the
        // endpoint, for all calls made by the service.
        $this->service->config['headers']['Cookie'] = $response->headers['set-cookie'];
      }

As the login endpoint returns the session_name and sessionid (services/resources/user_resource.inc _user_resource_login) Would it not be better to take the values returned from this to setup the session cookie? Looking I can't see a reason why not? If it doesn't look like a issue I can put a patch together.

Comments

ajevans85’s picture

StatusFileSize
new1.4 KB

Attached is a patch which fixes my issue.

Not being over familiar with the deploy module I guess this will break if using the XML-RPC server rather than the RestServer with JSON?

ajevans85’s picture

StatusFileSize
new1.37 KB

Not sure what happened with the above patch.

aspilicious’s picture

I had the same issue but I had some configuration problems:

Are you sure your url is configured correctl? (ending with services/rest)
Are you sure the endpoint has the correct resources enabled?

ajevans85’s picture

Yes the endpoints are all setup and working correctly, confirmed with using CURL and straight from the browser.

When the debug is enabled I get a successful login, it then iterates over each node posting to the remote service endpoint, the url is correct but each request results in a 'HTTP Error 401 Unauthorized' looking at the apache access logs on the remote server, this is the user is not set correctly via the session cookie for each post / put when sending the node. This is caused as we take the value straight from the 'set-cookie' header on the first login request, in my case 'set-cookie' has multiple values so is then handled wrong in the DeployAuthenticatorSession class. If it was a invalid endpoint issue I would be seeing a HTTP 404 error.

What is being sent as the session cookie as it's taken directly from login 'set-cookie' header:

ZDEDebuggerPresent=php,phtml,php3; path=/,SESSb50fde67a9f8d9abe7f9631416b7fd2e=gREQTXYr7h0-wrqiHoVcu7QexUmOfmvCXutHY2fxyKo; expires=Fri, 13-Apr-2012 15:40:01 GMT; path=/; domain=.sandbox; HttpOnly

What should be sent:

SESSb50fde67a9f8d9abe7f9631416b7fd2e=gREQTXYr7h0-wrqiHoVcu7QexUmOfmvCXutHY2fxyKo; expires=Fri, 13-Apr-2012 15:40:01 GMT; path=/; domain=.sandbox; HttpOnly

The patch I have submitted correctly sending the session id and token fixes the issue, if it was a invalid endpoint url the issue would still remain and I'd be seeing a different HTTP status code other than a 401.

aspilicious’s picture

Assigned: Unassigned » dixon_
Status: Active » Needs review

I'm assigning this to dixon_, I understand the problem and your solution but I'm not familiar enough with this to push this to dev. If I get a signoff from dixon_ I'll push this.

When you make patches be carefull with trailing whitespaces and tabs.

dixon_’s picture

Status: Needs review » Needs work

It makes sense what is mentioned in the OP. I guess it only works if you receive only one set-cookie in your response, which seems to be the case in my environment.

Looking at the patch there are some cosmetic problems:

+++ b/plugins/DeployAuthenticatorSession.inc
@@ -53,13 +53,13 @@ class DeployAuthenticatorSession implements DeployAuthenticator {
+      $response_data = drupal_json_decode($response->data);
+            ¶

Remove the whitespace.

+++ b/plugins/DeployAuthenticatorSession.inc
@@ -53,13 +53,13 @@ class DeployAuthenticatorSession implements DeployAuthenticator {
+      if($response_data['session_name'] && $response_data['sessid']){
+        $this->service->config['headers']['Cookie'] = $response_data['session_name'] . "=" . $response_data['sessid'] . ";";
+      } else {
+        throw new DeployAuthenticationException(t("No session was returned from the authentication request."));
       }

This if/else statement doesn't follow the Drupal coding standards.

aspilicious’s picture

Status: Needs work » Needs review
StatusFileSize
new1.73 KB

Rerolled, if this is ok, I'll rebase and commit.

ajevans85’s picture

Thank you, the re-rolled patch is working for me.

aspilicious’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.