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 ?

4 Answers 4


I was looking for a way to validate the checksum 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.


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:

    //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;
  • 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 ?
    – commonpike
    May 18, 2015 at 13:47
  • @commonpike Try the updated code and let me know if that works for you.
    – Laryn
    May 18, 2015 at 14:34
  • 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.
    – commonpike
    May 18, 2015 at 14:53
  • 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: github.com/civicrm/civicrm-core/blob/4.6/CRM/Core/…
    – Laryn
    May 18, 2015 at 15:22
  • 1
    To be precise, I used CRM_Contact_BAO_Contact_Utils::validChecksum($cid, $_GET["cs"])
    – commonpike
    May 28, 2015 at 11:53

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 :)


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).


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:

  • They both sound interesting. However, i want to send the mailing using CiviCRM. Can I access these features from within the mailing modile ?
    – commonpike
    May 15, 2015 at 13:17
  • 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.
    – Coleman
    May 15, 2015 at 22:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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