Answers.Body: <p>I was <a href="https://drupal.stackexchange.com/questions/140841/how-to-ensure-civicrm-checksum-cid-are-valid-in-custom-drupal-module">looking for a way to validate the checksum</a> at one point, too. Here's what I found:</p>
  
  <pre><code>CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $_GET["cs"])
  </code></pre>
  
  <p>which takes a CiviCRM contact id (<code>$cid</code>) and compares it to the checksum in the URL and did the trick for me.</p>
  
  <p><strong>UPDATE:</strong> </p>
  
  <p>It looks like the usage has changed slightly in core since I pulled the above out of there (although the above was still working for me). Below was <a href="https://github.com/civicrm/civicrm-core/blob/4.6/CRM/Core/Form.php#L1610-L1618" rel="nofollow noreferrer">taken from here</a>:</p>
  
  <pre><code>    //check if this is a checksum authentication
  $userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this);
  if ($userChecksum) {
    //check for anonymous user.
    $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($tempID, $userChecksum);
    if ($validUser) {
      return $tempID;
    }
  }
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-18T13:47:01.833Z
Answers.Text: Alsmost there. I can send a link with `{contact.contact_id}`  and `{contact.checksum}` from a CiviCRM mail template. But if I validate it using `CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $checksum)` it returns false. Am I .. expecting the wrong thing here ?
Answers.UserDisplayName: commonpike
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-18T14:34:37.580Z
Answers.Text: @commonpike Try the updated code and let me know if that works for you.
Answers.UserDisplayName: Laryn
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-18T14:53:41.260Z
Answers.Text: Thanks, but I dont see much difference. `$this` is a form, which I dont have, but i guess it gets a checksum. `$tempID` is a contact ID. I think.
Answers.UserDisplayName: commonpike
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-18T15:22:02.910Z
Answers.Text: Yes, $tempID is the contact ID. But taking a step back, I wonder if you can just use the function I pulled the code above from (ie. getContactID() ) and let CiviCRM do all the checking for you: https://github.com/civicrm/civicrm-core/blob/4.6/CRM/Core/Form.php#L1584-L1625
Answers.UserDisplayName: Laryn
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-28T11:52:26.143Z
Answers.Text: I used your first response - from before the update. Looking at it now, I think `CRM_Core_Form::getContactId()` might have done it better. It expects variables ?cid=XXX&cs=YYY on the request.
Answers.UserDisplayName: commonpike
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-28T11:53:27.700Z
Answers.Text: To be precise, I used `CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $_GET["cs"])`
Answers.UserDisplayName: commonpike
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-14T22:02:30.137Z
Answers.LastActivityDate: 2015-05-29T05:30:32.817Z
Answers.LastEditDate: 2017-04-13T12:47:16.150Z
Answers.UserDisplayName: Laryn
Answers.Body: <p>This extension is a bit experimental (read: not extensively tested, was old code, now bundled into an extension): <a href="https://civicrm.org/extensions/d7onetime" rel="nofollow noreferrer">https://civicrm.org/extensions/d7onetime</a></p>
  <p>It provides a CiviCRM token called <code>{d7onetime.url}</code> which can be included in emails or Scheduled Reminders (which can be practical for implementing better-looking welcome emails to users, adapted to their membership type).</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-02-26T21:01:48.380Z
Answers.LastActivityDate: 2021-02-26T21:01:48.380Z
Answers.UserDisplayName: bgm
Answers.Body: <p><em>CiviCRM intentionally doesn't provide login functionality for the CMS. Access bypass could have serious implications for your org - use with caution. You don't want to wake up in the newspaper because your membership DB got disclosed.</em></p>
  
  <p><em>Similarly, CiviCRM emails aren't treated the same way that password reset emails are. People forward CiviCRM emails a lot, and if you're providing login functionality you risk exposing user information when doing so.</em></p>
  
  <p><strong><em>Use the examples below with care.</em></strong></p>
  
  <hr>
  
  <p>If you want to use CiviCRM checksums to implement the same functionality as a Drupal login, you could do the following perhaps?</p>
  
  <ul>
  <li>Create a custom extension which provides a custom menu callback (eg <code>civicrm/user-login</code>).</li>
  <li>In your custom callback, identify the Drupal user and log them in. (This is really easy.</li>
  <li>Send out an email with a CiviCRM checksum pointed at this callback and perhaps with an additional parameter indicating the final destination URL.</li>
  <li>Perhaps add some checks to prevent it working for any users with "administer site configuration" permissions to limit the chance of abuse.</li>
  </ul>
  
  <p>You have code to validate a checksum above, so from here you'd want to -</p>
  
  <p><strong>Identify the user to match</strong></p>
  
  <pre><code>$params = array(
    'version' =&gt; 3,
    'sequential' =&gt; 1,
    'contact_id' =&gt; 1,
  );
  $result = civicrm_api('UFMatch', 'get', $params);
  // $uid is $result['values'][0]['uf_id'] or similar here.
  </code></pre>
  
  <p><strong>Load the matching user</strong></p>
  
  <pre><code>$account = user_load($uid);
  </code></pre>
  
  <p><strong>Check they aren't an admin (fairly arbitrary this)</strong></p>
  
  <pre><code>if (!user_access('administer site configuration', $account)) {
    // ...
  }
  </code></pre>
  
  <p><strong>Log them in</strong></p>
  
  <pre><code>global $user;
  $user = $account;
  </code></pre>
  
  <hr>
  
  <p>CiviCRM provides multiple concurrent checksums, since a user may have received one of several emails recently. Drupal provides only a single user login URL at a time.</p>
  
  <p>It is possible to add Drupal login URLs to an email, and you could do this by implementing your own custom token, BUT you'd have to play along with Drupal's login lifespan (24 or 48H?) and any other limitations. CiviCRM checksums will be easier to handle here, provided you can account for the security implications of doing this :)</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-29T06:25:16.200Z
Answers.LastActivityDate: 2015-05-29T06:58:13.163Z
Answers.LastEditDate: 2015-05-29T06:58:13.163Z
Answers.UserDisplayName: Chris Burgess
Answers.Body: <p>If you are really wanting to mail out a link that logs the user in, then it's not really a CiviCRM question, since authentication is handled by Drupal. Here are some modules that might help you:</p>
  
  <ul>
  <li><a href="https://www.drupal.org/project/urllogin" rel="nofollow">https://www.drupal.org/project/urllogin</a></li>
  <li><a href="https://www.drupal.org/project/email_auto_login" rel="nofollow">https://www.drupal.org/project/email_auto_login</a></li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-15T13:17:56.583Z
Answers.Text: They both sound interesting. However, i want to send the mailing using CiviCRM. Can I access these features from within the mailing modile ?
Answers.UserDisplayName: commonpike
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-15T22:02:33.110Z
Answers.Text: Not sure, you'd have to dig into the apis for those modules to see if their email tokens could be exposed using e.g. hook_civicrm_tokens.
Answers.UserDisplayName: Coleman
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-05-15T02:43:52.497Z
Answers.LastActivityDate: 2015-05-15T02:43:52.497Z
Answers.UserDisplayName: Coleman
Body: <p>I can send out personalized links from CiviCRM, as described here. 
  <a href="https://aghstrategies.com/content/how-create-one-click-personalized-links-civicrm-emails" rel="nofollow">https://aghstrategies.com/content/how-create-one-click-personalized-links-civicrm-emails</a></p>
  
  <p>They contain the contact id and a checksum that civicrm manages. Following the link will 'identify' the user.</p>
  
  <p>Can I use such a link to have a contact that has a Drupal account log in to Drupal ? </p>
  
  <p>I have a module in which I can create a menu router, validate the url, find a drupal id, log a user in, and redirect, I reckon. But to validate the url, I have to validate the checksum which afaik is not in the API, so I have to call the deep dark Core::BAODAO magic.</p>
  
  <p>Is there an easy way to do this ? </p>
  
  <p>If not, can someone sketch the BAODAO part ?</p>
  
Tags: <email><php><personal-campaign-pages>
Title: Personalized Drupal login link
ThreadText: # Personalized Drupal login link
  
  (Asked by: username_0 on 2015-05-14)
  
  I can send out personalized links from CiviCRM, as described here.
  <https://aghstrategies.com/content/how-create-one-click-personalized-links-civicrm-emails>
  
  They contain the contact id and a checksum that civicrm manages. Following the link will 'identify' the user.
  
  Can I use such a link to have a contact that has a Drupal account log in to Drupal ?
  
  I have a module in which I can create a menu router, validate the url, find a drupal id, log a user in, and redirect, I reckon. But to validate the url, I have to validate the checksum which afaik is not in the API, so I have to call the deep dark Core::BAODAO magic.
  
  Is there an easy way to do this ?
  
  If not, can someone sketch the BAODAO part ?
  
  **Tags:** email, php, personal-campaign-pages
  
  
  ---
  
  ## 4 answers
  
  ### Answer by username_1 on 2015-05-14. Score: 2 | Accepted answer
  
  I was [looking for a way to validate the checksum](https://drupal.stackexchange.com/questions/140841/how-to-ensure-civicrm-checksum-cid-are-valid-in-custom-drupal-module) at one point, too. Here's what I found:
  
  ```
  CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $_GET["cs"])
  
  ```
  
  which takes a CiviCRM contact id (`$cid`) and compares it to the checksum in the URL and did the trick for me.
  
  **UPDATE:**
  
  It looks like the usage has changed slightly in core since I pulled the above out of there (although the above was still working for me). Below was [taken from here](https://github.com/civicrm/civicrm-core/blob/4.6/CRM/Core/Form.php#L1610-L1618):
  
  ```
      //check if this is a checksum authentication
  $userChecksum = CRM_Utils_Request::retrieve('cs', 'String', $this);
  if ($userChecksum) {
    //check for anonymous user.
    $validUser = CRM_Contact_BAO_Contact_Utils::validChecksum($tempID, $userChecksum);
    if ($validUser) {
      return $tempID;
    }
  }
  
  ```
  
  > **Comments:**
  > **username_0**: Alsmost there. I can send a link with `{contact.contact_id}`  and `{contact.checksum}` from a CiviCRM mail template. But if I validate it using `CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $checksum)` it returns false. Am I .. expecting the wrong thing here ?  
  > **username_1**: @username_0 Try the updated code and let me know if that works for you.  
  > **username_0**: Thanks, but I dont see much difference. `$this` is a form, which I dont have, but i guess it gets a checksum. `$tempID` is a contact ID. I think.  
  > **username_1**: Yes, $tempID is the contact ID. But taking a step back, I wonder if you can just use the function I pulled the code above from (ie. getContactID() ) and let CiviCRM do all the checking for you: https://github.com/civicrm/civicrm-core/blob/4.6/CRM/Core/Form.php#L1584-L1625  
  > **username_0**: I used your first response - from before the update. Looking at it now, I think `CRM_Core_Form::getContactId()` might have done it better. It expects variables ?cid=XXX&cs=YYY on the request.  
  > **username_0**: To be precise, I used `CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $_GET["cs"])`  
  
  ---
  
  ### Answer by username_2 on 2021-02-26. Score: 1
  
  This extension is a bit experimental (read: not extensively tested, was old code, now bundled into an extension): <https://civicrm.org/extensions/d7onetime>
  
  It provides a CiviCRM token called `{d7onetime.url}` which can be included in emails or Scheduled Reminders (which can be practical for implementing better-looking welcome emails to users, adapted to their membership type).
  
  
  ---
  
  ### Answer by username_3 on 2015-05-29. Score: 1
  
  *CiviCRM intentionally doesn't provide login functionality for the CMS. Access bypass could have serious implications for your org - use with caution. You don't want to wake up in the newspaper because your membership DB got disclosed.*
  
  *Similarly, CiviCRM emails aren't treated the same way that password reset emails are. People forward CiviCRM emails a lot, and if you're providing login functionality you risk exposing user information when doing so.*
  
  ***Use the examples below with care.***
  
  ---
  
  If you want to use CiviCRM checksums to implement the same functionality as a Drupal login, you could do the following perhaps?
  
  * Create a custom extension which provides a custom menu callback (eg `civicrm/user-login`).
  * In your custom callback, identify the Drupal user and log them in. (This is really easy.
  * Send out an email with a CiviCRM checksum pointed at this callback and perhaps with an additional parameter indicating the final destination URL.
  * Perhaps add some checks to prevent it working for any users with "administer site configuration" permissions to limit the chance of abuse.
  
  You have code to validate a checksum above, so from here you'd want to -
  
  **Identify the user to match**
  
  ```
  $params = array(
    'version' => 3,
    'sequential' => 1,
    'contact_id' => 1,
  );
  $result = civicrm_api('UFMatch', 'get', $params);
  // $uid is $result['values'][0]['uf_id'] or similar here.
  
  ```
  
  **Load the matching user**
  
  ```
  $account = user_load($uid);
  
  ```
  
  **Check they aren't an admin (fairly arbitrary this)**
  
  ```
  if (!user_access('administer site configuration', $account)) {
    // ...
  }
  
  ```
  
  **Log them in**
  
  ```
  global $user;
  $user = $account;
  
  ```
  
  ---
  
  CiviCRM provides multiple concurrent checksums, since a user may have received one of several emails recently. Drupal provides only a single user login URL at a time.
  
  It is possible to add Drupal login URLs to an email, and you could do this by implementing your own custom token, BUT you'd have to play along with Drupal's login lifespan (24 or 48H?) and any other limitations. CiviCRM checksums will be easier to handle here, provided you can account for the security implications of doing this :)
  
  
  ---
  
  ### Answer by username_4 on 2015-05-15. Score: 0
  
  If you are really wanting to mail out a link that logs the user in, then it's not really a CiviCRM question, since authentication is handled by Drupal. Here are some modules that might help you:
  
  * <https://www.drupal.org/project/urllogin>
  * <https://www.drupal.org/project/email_auto_login>
  
  > **Comments:**
  > **username_0**: They both sound interesting. However, i want to send the mailing using CiviCRM. Can I access these features from within the mailing modile ?  
  > **username_4**: Not sure, you'd have to dig into the apis for those modules to see if their email tokens could be exposed using e.g. hook_civicrm_tokens.  
  
  ---
  
  