ldap->enabled() || ! $settings->auto_provision) { return null; } // Same refusals as an ordinary LDAP login — an empty or // whitespace-only password must never reach a bind. $identity = $this->ldap->attempt($email, $password); if ($identity === null) { return null; } // Same reason as SocialProvisioner: a deleted account keeps its // address until erasure removes the row, so provisioning over one // raises a QueryException at the moment of login. Refused here, the // sign-in fails the ordinary way instead, and a directory identity // does not silently reclaim an account somebody deleted. if (! $this->clients->addressIsFree($identity->email)) { Log::warning('A directory identity was not provisioned: the address belongs to a deleted account.', [ 'email' => $identity->email, ]); return null; } return $this->clients->provision( name: $identity->name, email: $identity->email, // A password they will never use and never learn: this account // authenticates against the directory. Generated rather than // left null so nothing downstream has to special-case an empty // hash, and never the directory password. password: Str::password(64), action: Action::LdapClientProvisioned, source: AuthSource::Ldap, ldapDn: $identity->dn, autoApprove: $settings->auto_approve, ); } }