Следующий шаг заключается в добавлении yii\authclient\AuthAction в веб контроллер и обеспечении реализации
successCallback
, выполняющий ваши требования.
class SiteController extends Controller
{
public function actions()
{
return [
'auth' => [
'class' => 'yii\authclient\AuthAction',
'successCallback' => [$this, 'onAuthSuccess'],
],
];
}
public function onAuthSuccess($client)
{
$attributes = $client->getUserAttributes();
/* @var $auth Auth */
$auth = Auth::find()->where([
'source' => $client->getId(),
'source_id' => $attributes['id'],
])->one();
if (Yii::$app->user->isGuest) {
if ($auth) { // авторизация
$user = $auth->user;
Yii::$app->user->login($user);
} else { // регистрация
if (isset($attributes['email']) && User::find()->where(['email' => $attributes['email']])->exists()) {
Yii::$app->getSession()->setFlash('error', [
Yii::t('app', "Пользователь с такой электронной почтой как в {client} уже существует, но с ним не связан. Для начала войдите на сайт использую электронную почту, для того, что бы связать её.", ['client' => $client->getTitle()]),
]);
} else {
$password = Yii::$app->security->generateRandomString(6);
$user = new User([
'username' => $attributes['login'],
'email' => $attributes['email'],
'password' => $password,
]);
$user->generateAuthKey();
$user->generatePasswordResetToken();
$transaction = $user->getDb()->beginTransaction();
if ($user->save()) {
$auth = new Auth([
'user_id' => $user->id,
'source' => $client->getId(),
'source_id' => (string)$attributes['id'],
]);
if ($auth->save()) {
$transaction->commit();
Yii::$app->user->login($user);
} else {
print_r($auth->getErrors());
}
} else {
print_r($user->getErrors());
}
}
}
} else { // Пользователь уже зарегистрирован
if (!$auth) { // добавляем внешний сервис аутентификации
$auth = new Auth([
'user_id' => Yii::$app->user->id,
'source' => $client->getId(),
'source_id' => $attributes['id'],
]);
$auth->save();
}
}
}
}
Метод successCallback
вызывается, когда пользователь был успешно аутентифицирован через внешний сервис. Через
экземпляр $client
мы можем извлечь полученную информацию. В нашем случае мы хотели бы:
Примечание: Могут потребоваться различные подходы обработки успешной аутентификации для различных клиентов аутентификации. Например: Twitter не допускает возвращение электронной почты пользователя, но так или иначе Вы должны с этим как то работать.
Хоть все клиенты и разные, всё же они реализуют базовый интерфейс yii\authclient\ClientInterface, который управляет общим API.
У каждого клиента есть некоторые описательные данные, которые могут использоваться в различных целях:
id
- уникальный идентификатор клиента, который отделяет его от других клиентов, может использоваться
в URL'ах, логах и т.д.name
- внешнее подлиное имя сервиса аутентификации, которое так же соответствует имени клиента. Различные
клиенты аутентификации могут иметь одно и то же имя, если они относятся к одному и тому же внешнему сервису
аутентификации.
Например: клиенты для Google OpenID и Google OAuth имеют одинаковое имя "google".
Данный атрибут может быть использован внутри баз данных, CSS стилей и так далее.title
- удобное для пользователя имя внешнего сервиса аутентификации, используется для предоставления клиента
аутентификации на уровне представления.Каждый клиент аутентификации имеет отличный от других процесс аутентификации, но каждый из них поддерживает метод
getUserAttributes()
, который может быть вызван, в случае, если аутентификация прошла успешно.
Это метод позволяет получить информацию о внешней учетной записи пользователя, такую, как ID, адрес электронной почты, полное имя, предпочитаемый язык и т.д. Обратите внимание, что для каждого внешнего сервиса в списке доступных полей может изменяться как название поля, так и сам факт его существования.
Определение списка атрибутов, возвращаемых внешним сервисом аутентификации, зависит от типа самого клиента:
requiredAttributes
и optionalAttributes
.scope
, обратите внимание, что разные сервисы используют
разные форматы для scope.Совет: если Вы используете несколько различных клиентов, Вы можете объединить структуры атрибутов, которые они возвращают, при помощиyii\authclient\BaseClient::$normalizeUserAttributeMap.
Оба клиента, yii\authclient\OAuth1 и yii\authclient\OAuth2, обеспечивают метод api()
, который может быть
использован для доступа к REST API внешнего сервиса аутентификации. Однако это метод очень простой и этого может быть
недостаточно, что бы получить полный доступ к функционалу внешнего API. Данный метод используется, в основном, для
получения данных внешней учетной записи пользователя.
Что бы использовать дополнительные обращения к API, необходимо настроить yii\authclient\BaseOAuth::$apiBaseUrl в соответствии со спецификацией API. Тогда Вы сможете вызвать метод yii\authclient\BaseOAuth::api():
use yii\authclient\OAuth2;
$client = new OAuth2;
// ...
$client->apiBaseUrl = 'https://www.googleapis.com/oauth2/v1';
$userInfo = $client->api('userinfo', 'GET');
В представлениях можно использовать готовый виджет yii\authclient\widgets\AuthChoice:
<?= yii\authclient\widgets\AuthChoice::widget([
'baseAuthUrl' => ['site/auth'],
'popupMode' => false,
]) ?>