A
A
Anton Natarov2016-05-11 13:04:37
Yii
Anton Natarov, 2016-05-11 13:04:37

Nodge - Yii2 EAuth - registration, Identity, how are you doing?

I use an extension for Yii2, social authorization. by Nodge
I have everything set up and everything works, but I want to do it right, but due to my little experience I can't come up with an elegant solution yet. Authorization works properly, I wrote my own registration.
Essence of the question:
Actually, I didn’t change much of the author’s code, I only expanded the receipt of attributes from Api-shek. The difficulty is that I get two Identity
Standard views: __id: 3
Social views: __id: vkontakte-484848
There is a code out of the box for Yii2 and you can pull out or show the profile for the current authorized user in this way. user and profile accounts are separated in the database, but linked one to one. those. their Ids are the same. I can get the profile like this:

$modelProfile = Profile::find()->where(['id' => Yii::$app->user->identity->id])->one();

since the USER model and the Identity method have been extended, you can still use the method I mentioned above. but the problem is that registration is implemented like this:
a new user is created. in the service_id, service_name field - the service user id and the service name are stuffed.
and now, in order to pull out the native account Id, you have to do something like this piece of code in each controller where there is an interaction.
protected function getSocialUser()
    {
        $identity = Yii::$app->getUser()->getIdentity();
        $user = User::find()->where(['service_id' => $identity->profile['id']])->one();
        $profile = Profile::find()->where(['id' => $user->id])->one();
        return $profile;
    }

And carry out checks at the places of receipt:
$model = $this->getSocialUser();
        if(!isset($model)){
            $model = $this->findModel(Yii::$app->user->identity->id);
        }

the reason that I do not create users with their own social Id. because there are more than 5 social networks. Therefore, I'm afraid there would be no duplicates. At the moment it works and everything is fine, but I don't like that it's +2 requests every time, the copy-paste of the code is constant. And it will not work to move the code to a separate model. many places use this approach. What solutions can be and how can you rewrite, take out the code? or change identity, otherwise store in the database?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander N++, 2016-05-11
@HanDroid

i made a separate table for social authorization
user - created an entry here
+
user_social - created an entry here if using authorization through the social network
vendor str (vk fb ya mr tw etc.)
user_id int
internal_id str
The user_social table was used only when logging in or registering from social networks. networks
If the required data is from social networks, I created campaign fields in the user or user_profile tables
UPD

public function actions()
    {
        return [
            'social' => [
                'class' => 'yii\authclient\AuthAction',
                'successCallback' => [$this, 'successCallback'],
            ],
        ];
    }

    /**
     * @param $client
     */
    public function successCallback($client)
    {
  $day = 86400;
        $client_id = Yii::$app->request->get('authclient');  // vk fb mr od etc
        $attributes = $client->getUserAttributes();             // result social data

        $userSocial = UserSocial::findOne(['client' => $client_id , 'internal_id' => $attributes['id'] ]);
        if(!$userSocial ){

            $user = new User;
            $user->scenario = 'social';

            if($user->register()){
                $userSocial = new UserSocial;
                $userSocial ->user_id = $user->id;
                $userSocial ->client  = $client_id;
                $userSocial ->internal_id = (string)$attributes['id'];
                $userSocial ->save();

                $prorile = $user->profile;
                $prorile->first_name = $attributes['first_name'];
                $prorile->last_name = $attributes['last_name'];
                $prorile->save();
            }
            Yii::$app->user->login($user, $day * 366 );
            Yii::$app->session->set('auth_social',[
                'client' => $client_id,
                'attributes' => $attributes,
                'token' => ''
            ]);

        }
        Yii::$app->user->login($user_social->user , $day * 366 );
    }

This is how I displayed a list of buttons through which to log in
<?php
        use yii\authclient\widgets\AuthChoice;
        $icons_id = [
            'vkontakte' => 1,
            'facebook' => 2,
            'tw' => 3,
            'mr' => 4,
            'odnoklassniki' => 5
        ];
        $authAuthChoice = AuthChoice::begin([
            'baseAuthUrl' => ['auth/social'],
        ]);?>
        <ul class="social-auth-list">
            <?php foreach ($authAuthChoice->getClients() as $client): ?>
                <li>
                    <a data-popup-width="500" data-popup-height="430"
                        href="<?= $authAuthChoice->createClientUrl($client)?>"><i class="ico ico-soc-<?=$icons_id[$client->getId()]?>"></i></a>
                </li>
            <?php endforeach; ?>
        </ul>
        <?php AuthChoice::end(); ?>

In config
'authClientCollection' => [
            'class' => 'yii\authclient\Collection',
            'clients' => [
                'vkontakte' => [
                    'class' => 'yii\authclient\clients\VKontakte',
                    'clientId' => '1',
                    'clientSecret' => 'vW5AYsdsd',
                    'scope' => 'friends,email,offline',
                ],
                'facebook' => [
                    'class' => 'yii\authclient\clients\Facebook',
                    'clientId' => '1',
                    'clientSecret' => 'vW5AYsdsd',
                ],
                'odnoklassniki' => [
                    'class' => 'app\components\authclient\clients\Odnoklassniki',
                    'clientId' => '1',
                    'clientSecret' => 'F12sdsd',
                    'application_public_key' => 'vW5AYsdsdsdsd',
                    'scope' => 'VALUABLE_ACCESS'
                ],

            ],
        ],

For WhatsApp
<?php
namespace app\components\authclient\clients;
use yii\authclient\OAuth2;

/**
 * Class Odnoklassniki
 * @package app\components\authclient\clients
 * Example application configuration:
 *
 * ~~~
 * 'components' => [
 *     'authClientCollection' => [
 *         'class' => 'yii\authclient\Collection',
 *         'clients' => [
 *             'odnoklassniki' => [
 *                 'class' => 'yii\authclient\clients\odnoklassniki',
 *                 'clientId' => 'app_client_id',
 *                 'clientSecret' => 'application_client_secret',
 *                 'application_public_key' => 'application_public_key',
 *                 'scope' => 'VALUABLE_ACCESS'
 *             ],
 *         ],
 *     ]
 *     ...
 * ]
 */
class Odnoklassniki  extends OAuth2
{
    /**
     * @inheritdoc
     */
    public $authUrl = 'http://www.odnoklassniki.ru/oauth/authorize';
    /**
     * @inheritdoc
     */
    public $tokenUrl = 'http://api.odnoklassniki.ru/oauth/token.do';
    /**
     * @inheritdoc
     */
    public $apiBaseUrl = 'http://api.odnoklassniki.ru/fb.do';

    public $application_public_key;

    /**
     * @inheritdoc
     */
    protected function initUserAttributes()
    {
       return $this->api('','GET',[
           'method' => 'users.getCurrentUser',
           'format' => 'JSON',
           'application_key' => $this->application_public_key,
           'client_id' => $this->clientId,
       ]);
    }

    /**
     * @inheritdoc
     */
    protected function apiInternal($accessToken, $url, $method, array $params, array $headers)
    {
        $access_token = $accessToken->getToken();
        if (count($params)) {
            $param_str = '';
            ksort($params);
            foreach ($params as $k => $v)
            {
                $param_str .= $k . '=' . $v;
            }
            $params['sig'] = md5($param_str . md5($access_token . $this->clientSecret));
        }
        $params['access_token'] = $access_token;
        return $this->sendRequest($method, trim($url,'/'), $params, $headers);
    }

    /**
     * @inheritdoc
     */
    protected function defaultName()
    {
        return 'odnoklassniki';
    }

    /**
     * @inheritdoc
     */
    protected function defaultTitle()
    {
        return 'Odnoklassniki';
    }

    /**
     * @inheritdoc
     */
    protected function defaultNormalizeUserAttributeMap()
    {
        return [
            'id' => 'uid'
        ];
    }

}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question