Problem/Motivation

In issue #3023470: Provide consistent response from createDrupalUser and calling functions and commit d492750c \Drupal\ldap_user\Processor\DrupalUserProcessor::provisionDrupalAccount() returns FALSE if DrupalUserProcessor::createDrupalUser() returns FALSE, however DrupalUserProcessor::createDrupalUser() doesn't always return a Boolean, once $this->saveAccount() is called the function effectively returns NULL meaning that the if statement at the end of DrupalUserProcessor::provisionDrupalAccount() will always evaluate to FALSE even if the user has been created.

In reality the result of this is that when for example LDAP SSO creates a new User by the user navigating to /user/login/sso, instead of the User being automatically logged in they will be taken back to the login form with the error message Sorry, your LDAP credentials were not found or the LDAP server is not available. You may log in with other credentials on the login form., however in reality the new User is still created so by navigating to /user/login/sso again they are automatically logged in on every future login attempt.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

AaronMcHale created an issue. See original summary.

aaronmchale’s picture

Assigned: aaronmchale » Unassigned
Status: Active » Needs review
StatusFileSize
new1 KB

So this patch technically fixes the issue but since $this->saveAccount() doesn't actually return anything and the next line if (!$this->account) { as far as I can tell will never actually evaluate to TRUE, so I'm not totally convinced that the error handling in place to catch and inform of the User Entity saving failing will work.

If the User Entity does fail to save \Drupal\Core\Entity\EntityStorageException will be thrown (see EntityInterface::save), which as far as I can tell means that this is redundant:

    $this->saveAccount();
    if (!$this->account) {
      drupal_set_message(t('User account creation failed because of system problems.'), 'error');
      return FALSE;
    }

So, I'm setting to needs review because technically speaking the user-facing issue is resolved, but in my opinion DrupalUserProcessor::createDrupalUser should either: always return TRUE beyond $this->saveAccount() and the if statement after it should just be removed, or wrap $this->saveAccount() in a try catch block and return FALSE if \Drupal\Core\Entity\EntityStorageException is thrown. However, I'm not at all a fan of catching exceptions like that, because if an exception is thrown in the Entity Storage you really need that to bubble up so that the administrator becomes aware of it. So in my opinion the end of DrupalUserProcessor::createDrupalUser really should just look like:

    $this->saveAccount();
    ExternalAuthenticationHelper::setUserIdentifier($this->account, $this->account->getAccountName());
    return TRUE;

Because, again, if something did do wrong at $this->saveAccount() the next line will never be reached because \Drupal\Core\Entity\EntityStorageException will be thrown.

  • grahl committed 479470b on 8.x-4.x authored by AaronMcHale
    Issue #3054442 by AaronMcHale: Regression: provisionDrupalAccount...
grahl’s picture

Status: Needs review » Fixed

Hi Aaron

Thanks for the detailed feedback, your explanation makes perfect sense. I've therefore removed the unreachable check as suggested from the 4.x branch (since we already got another TRUE result in 3.x in the other issue). The return values are a bit of a mess in 4.x at the moment so it returns nothing but I'll fix that in #3023470: Provide consistent response from createDrupalUser and calling functions.

aaronmchale’s picture

@grahl great thanks for that

Status: Fixed » Closed (fixed)

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