0

Looking at my logs I have an issue. I have not been able to recreate it myself.

I have a form which an anonymous user fills out. This form takes an email address. When submitting the form I take that email address and either log the user in or create an account and log the user in.

This code is working fine. As I have several watchdog() calls going in as the user who has been logged in.

The code then creates an order in Drupal commerce (with the user account above). I have a valid orderid created with the above user.

I then have:

watchdog('MyMod', t("Logged in as user));
drupal_goto('checkout/' . $orderid . '/review');

The watchdog() goes in as the user. When I hit checkout/????/review I then get an access denied for an Anonymous user.

This is only happening some of the time. As I said I have not been able to reproduce. What could be causing the drupal_goto() to log my user out.

Update

I now use

watchdog('MyMod', t("Insert in ref table complete"));
$formstate['redirect'] = 'checkout/' . $orderid . '/review';

To redirect my user however I am still getting the same issue.

Update 2

With some code.

Log out user

function _mymod_logout_user() {
  global $user;
  if ($user->uid > 1) {
    module_invoke_all('user_logout', $user);
    session_destroy();
  }
}

Create User

function _mymod_create_user($mail) {
  global $user;
  _mymod_logout_user();
  if ($user->uid != 0) {
    return $user;
  }

  $account = user_load_by_mail($mail);

  if ($account == FALSE) {


    $password = 'random12!££SsjsjaJAAJA3'; //made up

    //set up the user fields
    $fields = array(
      'name' => $mail,
      'mail' => $mail,
      'pass' => $password,
      'status' => 1,
      'init' => 'email address',
      'roles' => array(
        DRUPAL_AUTHENTICATED_RID => 'authenticated user',
      ),
    );

    $account = user_save('', $fields);
  }

  // If the user is 1 then we want to return false as they will be logged in as admin
  if ($account->uid == 1) {
    return FALSE;
  }

  $form_state = array();
  $form_state['uid'] = $account->uid;
  user_login_submit(array(), $form_state);

  return $account;
}

Create Order

function _mymod_create_order($sku, $mail) {
  global $user;
  $user = _mymod_create_user($mail);

  // User is trying to create an account under user 1 so return nothing.
  // can only do this if logged in a user 1 not anon
  if ($user == FALSE) {
    return;
  }
  $uid = $user->uid;

  $order = commerce_order_new($uid, 'checkout_review');
  $product = commerce_product_load_by_sku($sku);
  $line_item = commerce_product_line_item_new($product, 1, $order->order_id, array());
  commerce_line_item_save($line_item);

  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $order_wrapper->commerce_line_items[] = $line_item;
  commerce_order_save($order);
  return $order->order_id;
}

Insert into custom table

function _mymod_insert_ref_table($orderid, $ref) {
  db_insert('mymod_reference_table')
    ->fields(array(
      'orderid' => $orderid,
      'ref' => $ref,
    ))
    ->execute();
}

Form submit function

function mymod_form_submit($form, &$formstate) {
  global $conf;

  $sku = //Code that generates a SKU;

  $orderid = _mymod_create_order($sku, $form['email']['#value']); //email has all ready been validated by drupal

  $ref = // Call to WS that returns a reference number
  _mymod_insert_ref_table($orderid, $ref);
  watchdog('My Mod', t("Insert in ref table complete")); // This watchdog message goes in as the logged in user!
  $formstate['redirect'] = 'checkout/' . $orderid . '/review';  // When I reach this page I am logged out sometimes...

}
  • Logging in a user simply based on an e-mail address sounds dicey - how are you preventing illegitimate account access? – Ryan Szrama Feb 18 '14 at 20:41
  • Personal information is not stored. Order history is not visible. After the order has been created passed via web services to a third party system. Can then view status of order from there. – user13134 Feb 20 '14 at 15:25
2

You should better use $form['redirect'] within a form rather than drupal_goto().

If you use drupal_goto() you will short cut the form processing skipping any other form_submission functions that have attached themselves to the form. Thus, if you use path_auto and do a drupal_goto while processing a node form, a nice path will not be added to your node because the drupal_goto() was executed before pathauto's node submission handler was called.

Source

This was before the original post was edited. Regarding the logout issue, let us review your procedure.

So essentially: when a form is submitted, mymod_form_submit() calls _mymod_create_order(), which calls _mymod_create_user(), which in turn calls _mymod_logout_user(). All of them unconditionally so far.

If not user 1, you will logout the user and then back in _mymod_create_user() you will attempt to create if necessary and then log the user in.

When you attempt to login the user via user_login_submit(), Drupal will call drupal_session_regenerate(). There, in an attempt to prevent several nasty security possibilities such as session fixation, will generate a new session ID. I suspect the trouble is somewhere there, depending on what exactly happens in the code that displays the redirection page "checkout/...".

In order to deal with this issue I would recommend you to adopt the procedure that other modules use to deal with the possibility that an anonymous user needs to login / be created. Ubercart and Drupal Commerce certainly deal with that. Personally I would suggest to take a look at Ubercart file "uc_cart/uc_cart.pages.inc", function uc_cart_checkout()

  • (Assuming that drupal_goto() is happening indeed in the form processing, no code provided. – Wtower Feb 14 '14 at 11:33
  • The code is being executed in the form submit function. – user13134 Feb 14 '14 at 11:46
  • I have changed my code. Will monitor the logs and will see what happens. – user13134 Feb 14 '14 at 12:03
  • sadly this did solve the issue. It appeared again today. – user13134 Feb 20 '14 at 15:23
  • You mean it did not? The principle is correct though. Please post some code. – Wtower Feb 20 '14 at 15:37
0

I've seen issues with user appearing to get logged out when the site can be accessed both through http://www.domain.com and http://domain.com: The drupal_goto() call could send them from one version to the other, thus voiding the session cookie. Have you tried using .htaccess to redirect the www.domain.com to domain.com, or the other way around?

  • We have the base_url set in the config file as subdomain.domain.com. We have a rewrite rule to redirect http traffic to https. This is one outside of apache. – user13134 Feb 21 '14 at 10:24
  • Just make sure that apache doesn't also allow www.subdomain.domain.com. There are instructions in .htaccess to avoid that – Ollie Feb 21 '14 at 11:00
  • http-->https rewrite could break sessions, too... – Ollie Feb 21 '14 at 11:21
0

Check out if protocol changes. If you are being sent http to https, the http session won't continue into https.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.