/** * Handle successful authentication * * @param \yii\authclient\BaseClient $authClient * @return Response */ public function onAuthSuccess(\yii\authclient\BaseClient $authClient) { $attributes = $authClient->getUserAttributes(); // User already logged in - Add new authclient to existing user if (!Yii::$app->user->isGuest) { AuthClientHelpers::storeAuthClientForUser($authClient, Yii::$app->user->getIdentity()); return $this->redirect(['/user/account/connected-accounts']); } // Login existing user $user = AuthClientHelpers::getUserByAuthClient($authClient); if ($user !== null) { return $this->login($user, $authClient); } if (!$authClient instanceof ApprovalBypass && !Yii::$app->getModule('user')->settings->get('auth.anonymousRegistration')) { Yii::$app->session->setFlash('error', Yii::t('UserModule.base', "You're not registered.")); return $this->redirect(['/user/auth/login']); } // Check if E-Mail is given if (!isset($attributes['email'])) { Yii::$app->session->setFlash('error', "Missing E-Mail Attribute from AuthClient."); return $this->redirect(['/user/auth/login']); } if (!isset($attributes['id'])) { Yii::$app->session->setFlash('error', "Missing ID AuthClient Attribute from AuthClient."); return $this->redirect(['/user/auth/login']); } // Check if e-mail is already taken if (User::findOne(['email' => $attributes['email']]) !== null) { Yii::$app->session->setFlash('error', Yii::t('UserModule.base', 'User with the same email already exists but isn\'t linked to you. Login using your email first to link it.')); return $this->redirect(['/user/auth/login']); } // Try automatically create user & login user $user = AuthClientHelpers::createUser($authClient); if ($user !== null) { return $this->login($user, $authClient); } // Make sure we normalized user attributes before put it in session (anonymous functions) $authClient->setNormalizeUserAttributeMap([]); // Store authclient in session - for registration controller Yii::$app->session->set('authClient', $authClient); // Start registration process return $this->redirect(['/user/registration']); }
/** * Converts service attributes to app\modules\user\models\User model attributes * @param \yii\authclient\BaseClient $client * @return array Array of attributes by model type which we can apply by $model->setAttributes() */ public static function mapUserAttributesWithService(\yii\authclient\BaseClient $client) { $mappings = ['service' => ['service_id' => static::$ServiceIdMapping], 'user' => ['username' => ['app\\modules\\user\\authclients\\GitHub' => 'login', 'yii\\authclient\\clients\\Twitter' => 'screen_name', 'app\\modules\\user\\authclients\\VKontakte' => 'nickname', 'yii\\authclient\\clients\\YandexOAuth' => 'login'], 'email' => ['app\\modules\\user\\authclients\\GitHub' => 'email', 'yii\\authclient\\clients\\YandexOpenId' => 'email', 'app\\modules\\user\\authclients\\Facebook' => 'email', 'yii\\authclient\\clients\\YandexOAuth' => 'default_email'], 'first_name' => ['app\\modules\\user\\authclients\\Facebook' => 'first_name', 'app\\modules\\user\\authclients\\VKontakte' => 'first_name', 'yii\\authclient\\clients\\YandexOAuth' => 'first_name'], 'last_name' => ['app\\modules\\user\\authclients\\Facebook' => 'last_name', 'app\\modules\\user\\authclients\\VKontakte' => 'last_name', 'yii\\authclient\\clients\\YandexOAuth' => 'last_name'], 'avatar_url' => ['app\\modules\\user\\authclients\\GitHub' => 'avatar_url', 'yii\\authclient\\clients\\Twitter' => 'profile_image_url', 'app\\modules\\user\\authclients\\VKontakte' => 'photo'], 'company' => ['app\\modules\\user\\authclients\\GitHub' => 'company'], 'url' => ['app\\modules\\user\\authclients\\GitHub' => 'html_url'], 'location' => ['app\\modules\\user\\authclients\\GitHub' => 'location']]]; $class_name = $client->className(); $attributes = $client->getUserAttributes(); $result = []; foreach ($mappings as $model_type => $mappings_by_attribute) { $result[$model_type] = []; foreach ($mappings_by_attribute as $attribute => $maps) { if (isset($maps[$class_name])) { $key_in_attributes = $maps[$class_name]; $value = null; if (is_array($key_in_attributes)) { $value = []; foreach ($key_in_attributes as $key) { if (isset($attributes[$key])) { $value[] = $attributes[$key]; } } if (count($value) > 0) { $value = implode(' ', $value); } else { $value = null; } } else { $value = isset($attributes[$key_in_attributes]) ? $attributes[$key_in_attributes] : null; } if ($value !== null) { $result[$model_type][$attribute] = $value; } } } } return $result; }
public function socialRegistrationScenario(RegistrationForm &$registrationForm, BaseClient &$client) { if (empty($registrationForm->username)) { $registrationForm->generateUsername($client->getUserAttributes()); $registrationForm->username_is_temporary = true; } if (empty($registrationForm->password)) { $registrationForm->password = PasswordHelper::generate(UsersModule::module()->generatedPasswordLength); } }
/** * @param \yii\authclient\BaseClient $client */ function __construct($client) { /** * 初始化模型参数 */ $this->attributes = $client->getUserAttributes(); $this->type = $client->getId(); switch ($this->type) { case 'tencent': $this->openId = $this->attributes['openid']; $this->avatar = $this->attributes['figureurl_2'] . '.png'; $this->username = $this->attributes['nickname']; $this->email = ''; break; case 'weibo': $this->openId = $this->attributes['id']; $this->avatar = strpos($this->attributes['avatar_hd'], '.jpg') ? $this->attributes['avatar_hd'] : $this->attributes['avatar_hd'] . '.jpg'; $this->username = $this->attributes['name']; $this->email = ''; break; case 'github': $this->openId = $this->attributes['id']; $this->avatar = $this->attributes['avatar_url'] . '.jpg'; $this->username = $this->attributes['name']; $this->email = $this->attributes['email']; break; case 'google': $this->openId = $this->attributes['id']; $this->avatar = str_replace("?sz=50", "", str_replace("https://", "http://", $this->attributes['image']['url'])); $this->username = $this->attributes['displayName']; $this->email = $this->attributes['emails'][0]['value']; break; default: $this->openId = ''; $this->avatar = ''; $this->username = ''; $this->email = ''; break; } /** * 检查模型的邮箱和名字是否存在 */ $this->checkEmail(); $this->checkUserName(); }
/** * Connect social auth to the logged-in user * @param \yii\authclient\BaseClient $client * @return \yii\web\Response * @throws \yii\web\ForbiddenHttpException */ public function connectCallback($client) { // uncomment this to see which attributes you get back //echo "<pre>";print_r($client->getUserAttributes());echo "</pre>";exit; // check if user is not logged in. if so, do nothing if (Yii::$app->user->isGuest) { return; } // check duplicates by provider_id $attributes = $client->getUserAttributes(); if ($this->checkIsAlreadyConnected($attributes['id'])) { // register a new user $userAuth = $this->initUserAuth($client); $userAuth->setUser(Yii::$app->user->id)->save(); } else { Yii::$app->session->setFlash('Connect-danger', Yii::t('user', 'This account has already been connected')); } }
/** * TODO: допилить, разделить * @param \yii\authclient\BaseClient $client * @return bool */ public function successAuthclientCallback($client) { $attributes = $client->getUserAttributes(); //TODO: добавить обновление данных if (!Yii::$app->getUser()->isGuest) { $userAuthClient = \common\models\UserAuthclient::findOne(["user_id" => Yii::$app->user->getId(), "provider" => $client->getId(), "provider_identifier" => $attributes["id"]]); if (!$userAuthClient) { $userAuthClient = new \common\models\UserAuthclient(["user_id" => Yii::$app->user->getId(), "provider" => $client->getId(), "provider_identifier" => $attributes["id"], "provider_data" => serialize($attributes)]); $userAuthClient->save(); } } else { $userAuthClient = \common\models\UserAuthclient::findOne(["provider" => $client->getId(), "provider_identifier" => $attributes["id"]]); if ($userAuthClient) { $user = \common\models\User::findIdentity($userAuthClient->getUserId()); if ($user) { return Yii::$app->user->login($user, 0); } } } }
/** * Register a new user using client attributes and then associate userAuth * @param \yii\authclient\BaseClient $client * @param \amnah\yii2\user\models\UserAuth $userAuth */ protected function registerAndLoginUser($client, $userAuth) { /** @var \amnah\yii2\user\models\User $user */ /** @var \amnah\yii2\user\models\Profile $profile */ /** @var \amnah\yii2\user\models\Role $role */ $role = $this->module->model("Role"); // set user and profile info $attributes = $client->getUserAttributes(); $function = "setInfo" . ucfirst($client->name); // "setInfoFacebook()" list($user, $profile) = $this->{$function}($attributes); // calculate and double check username (in case it is already taken) $fallbackUsername = "******"; $user = $this->doubleCheckUsername($user, $fallbackUsername); // save new models $user->setRegisterAttributes($role::ROLE_USER, $user::STATUS_ACTIVE)->save(); $profile->setUser($user->id)->save(); $userAuth->setUser($user->id)->save(); // log user in Yii::$app->user->login($user, $this->module->loginDuration); }
protected function mapServiceAttributes(BaseClient &$client, Model &$model) { $clientUserAttributes = $client->getUserAttributes(); // go through native client attributes foreach ($clientUserAttributes as $attribute => $value) { if ($model->canSetProperty($attribute) || in_array($attribute, $model->attributes())) { $model->{$attribute} = $value; } } // now find mapping for this service $map = SocialMappings::mapForSocialService($this->socialServiceId); foreach ($map as $modelAttribute => $socialAttribute) { $value = []; foreach ($socialAttribute as $attribute) { $attribute = trim($attribute); if (isset($clientUserAttributes[$attribute])) { $attributeValue = trim($clientUserAttributes[$attribute]); if (!empty($attributeValue)) { $value[] = $clientUserAttributes[$attribute]; } } } $value = implode(' ', $value); if (!empty($value)) { $model->{$modelAttribute} = $value; } } }
/** * Social client authorization callback * * @param \yii\authclient\BaseClient $client * * @return \yii\web\Response * @throws BadRequestHttpException */ public function onAuthSuccess($client) { /** * @var SocialProfile $socialClass * @var User $userClass * @var SocialProfile $auth * @var User $user * @var AuthEvent $event */ $socialClass = $this->fetchModel(Module::MODEL_SOCIAL_PROFILE); $userClass = $this->fetchModel(Module::MODEL_USER); $attributes = $client->getUserAttributes(); $clientId = $client->getId(); $clientTitle = $client->getTitle(); $sourceId = (string) $attributes['id']; $email = $client->getEmail(); $username = $client->getUsername(); // generate random username if username is empty, less than min length, or random usernames have been enabled $randomUsernameGenerator = $this->getConfig('registrationSettings', 'randomUsernameGenerator', ["delimiter" => "."]); if (empty($username) || $username < $this->getConfig('registrationSettings', 'minUsernameLength', 5) || $this->getConfig('registrationSettings', 'randomUsernames', false)) { $i = 0; do { if (is_callable($randomUsernameGenerator)) { $username = call_user_func($randomUsernameGenerator); } else { $username = Haikunator::haikunate($randomUsernameGenerator); } $i++; } while ($i < 10 && $userClass::find()->where(['username' => $username])->exists()); unset($i); } $event = new AuthEvent(); $event->client = $client; $event->userClass = $userClass; $event->socialClass = $socialClass; $auth = $socialClass::find()->where(['source' => $clientId, 'source_id' => $attributes['id']])->one(); $event->model = $auth; $this->_module->trigger(Module::EVENT_AUTH_BEGIN, $event); $transaction = static::tranInit($event); try { if (Yii::$app->user->isGuest) { if ($auth) { // login $user = $auth->user; Yii::$app->user->login($user); $event->flashType = 'success'; $event->message = Yii::t('user', 'Logged in successfully with your <b>{client}</b> account.', ['client' => $clientTitle]); $event->result = AuthEvent::RESULT_LOGGED_IN; } else { // signup if (!empty($email) && $userClass::find()->where(['email' => $email])->exists()) { $event->flashType = 'error'; $event->message = Yii::t('user', 'User with the same email as in <b>{client}</b> account already exists but is not linked to it. Login using email first to link it.', ['client' => $clientTitle]); $event->result = AuthEvent::RESULT_DUPLICATE_EMAIL; } else { $minPassLen = $this->getConfig('registrationSettings', 'randomPasswordMinLength', 10); $maxPassLen = $this->getConfig('registrationSettings', 'randomPasswordMaxLength', 14); $password = Yii::$app->security->generateRandomString(rand($minPassLen, $maxPassLen)); $user = new $userClass(['username' => $username, 'email' => $email, 'password' => $password]); $user->generateAuthKey(); $success = false; if ($user->save()) { $auth = new $socialClass(['user_id' => $user->id, 'source' => $clientId, 'source_id' => $sourceId]); if ($auth->save()) { $transaction->commit(); $success = true; Yii::$app->user->login($user); } } if (!$success) { $event->result = AuthEvent::RESULT_SIGNUP_ERROR; $event->flashType = 'error'; $event->message = Yii::t('user', 'Error while authenticating <b>{client}</b> account.<pre>{errors}</pre>', ['client' => $clientTitle, 'errors' => print_r($user->getErrors(), true)]); throw new Exception('Error authenticating social client'); } else { $event->result = AuthEvent::RESULT_SIGNUP_SUCCESS; $event->flashType = 'success'; $event->message = Yii::t('user', 'Logged in successfully with your <b>{client}</b> account.', ['client' => $clientTitle]); } } } } else { // user already logged in if (!$auth) { // add auth provider $user = Yii::$app->user; $id = $user->id; $auth = new $socialClass(['user_id' => $id, 'source' => $clientId, 'source_id' => $attributes['id']]); $event->model = $auth; if ($auth->save()) { $transaction->commit(); $event->result = AuthEvent::RESULT_LOGGED_IN; $event->flashType = 'success'; $event->message = Yii::t('user', 'Successfully authenticated <b>{client}</b> account for <b>{user}</b>.', ['client' => $clientTitle, 'user' => $user->username]); } else { $event->result = AuthEvent::RESULT_AUTH_ERROR; $event->flashType = 'error'; $event->message = Yii::t('user', 'Error while authenticating <b>{client}</b> account for <b>{user}</b>.<pre>{errors}</pre>', ['client' => $clientTitle, 'errors' => print_r($auth->getErrors(), true)]); throw new Exception('Error authenticating social client'); } } else { $event->result = AuthEvent::RESULT_LOGGED_IN; $event->flashType = 'success'; $event->message = Yii::t('user', 'You have already connected your <b>{client}</b> account previously. Logged in successfully.', ['client' => $clientTitle]); } } } catch (Exception $e) { static::tranRollback($transaction); $this->raise($e, $event); } $this->_module->trigger(Module::EVENT_AUTH_COMPLETE, $event); static::setFlash($event); if (!isset($event->redirectUrl)) { $event->redirectUrl = $this->fetchUrl('loginSettings', 'loginRedirectUrl'); } return $this->redirect($event->redirectUrl); }