Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with authorization through social network new user. Return 404 #383

Open
grozzzny opened this issue Jun 5, 2020 · 19 comments
Open

Comments

@grozzzny
Copy link

grozzzny commented Jun 5, 2020

throw new NotFoundHttpException();

Pls, help me. The problem with authorization through social network new user. Return 404 /user/registration/connect?code=FMwHPLCI*****************DJC

    // Da\User\Controller\RegistrationController
    public function actionConnect($code)
    {
        /** @var SocialNetworkAccount $account */
        $account = $this->socialNetworkAccountQuery->whereCode($code)->one();
        if ($account === null || $account->getIsConnected()) {
            throw new NotFoundHttpException(); // !!!!!!!!!!  social_account not saved
        }
        ...
}
// Da\User\Service\SocialNetworkAuthenticateService
protected function createAccount()
    {
        $data = $this->client->getUserAttributes();

        /** @var SocialNetworkAccount $account */
        $account = $this->controller->make(
            SocialNetworkAccount::class,
            [],
            [
                'provider' => $this->client->getId(),
                'client_id' => $data['id'],
                'data' => json_encode($data),
                'username' => $this->client->getUserName(),
                'email' => $this->client->getEmail(),
            ]
        );
        // !!!!!!!!!!!!!!!!! User not found => social_account not save
        if (($user = $this->getUser($account)) instanceof User) {
            $account->user_id = $user->id;
            $account->save(false);
        }

        return $account;
    }
@grozzzny
Copy link
Author

grozzzny commented Jun 5, 2020

I tried all events. The problem is solved only this way, otherwise redirecting to 404

Config. Event beforeAuthenticate handler

 'user' => [
            'class' => Da\User\Module::class,
            'controllerMap' => [
 'security' => [
                    'class' => 'Da\User\Controller\SecurityController',
                    'on beforeAuthenticate' => ['app\components\SocialNetworkHandler', 'beforeAuthenticate']
                ],
     ],
],

file components/SocialNetworkHandler.php

<?php


namespace app\components;


use Da\User\Event\SocialNetworkAuthEvent;
use Da\User\Factory\MailFactory;
use Da\User\Model\User;
use Da\User\Service\UserCreateService;
use Yii;
use yii\base\BaseObject;

class SocialNetworkHandler extends BaseObject
{
    /**
     * @param SocialNetworkAuthEvent $event
     */
    public static function beforeAuthenticate($event)
    {
        /** @var User $model */
        $user = Yii::$container->get(User::class);

        if($user::find()->where(['email' => $event->client->email])->exists()) return;

        $user = new $user([
            'scenario' => 'create',
            'email' => $event->client->email,
            'username' => $event->client->username,
            'password' => null
        ]);

        /** @var MailFactory $mailFactory */
        $mailFactory = Yii::$container->get(MailFactory::class);
        $mailService = $mailFactory::makeWelcomeMailerService($user);

        /** @var UserCreateService $userCreateService */
        $userCreateService = Yii::$container->get(UserCreateService::class, [$user, $mailService]);
        $userCreateService->run();

        $event->account->user_id = $user->id;
        $event->account->save();

        Yii::$app->user->login($user);
    }
}

@mkodummy
Copy link

I also noticed this bug.
i fixed it moving save(false) outside the IF statement. ugly fix though.

BEFORE

        if (($user = $this->getUser($account)) instanceof User) {
            $account->user_id = $user->id;
            $account->save(false);
        }

AFTER

        if (($user = $this->getUser($account)) instanceof User) {
            $account->user_id = $user->id;
       }
       $account->save(false);

@mkodummy
Copy link

@grozzzny from your code I made an even simpler fix. Thanks for the insight on the beforeAuthenticate hook. My final SocialNetworkHandler.php file is only the code below. Rest is exactly the same as you pointed out.

class SocialNetworkHandler extends BaseObject
{
    /**
     * @param SocialNetworkAuthEvent $event
     */
    public static function beforeAuthenticate($event)
    {
        return $event->account->save(false);
    }
}

Saving the social account like above already unlocks the entire user registration/welcome email etc. stuff existing, in my project the code below is redundant ( of course, unless you are customizing it)

 $user = new $user([
            'scenario' => 'create',
            'email' => $event->client->email,
            'username' => $event->client->username,
            'password' => null
        ]);

        /** @var MailFactory $mailFactory */
        $mailFactory = Yii::$container->get(MailFactory::class);
        $mailService = $mailFactory::makeWelcomeMailerService($user);

        /** @var UserCreateService $userCreateService */
        $userCreateService = Yii::$container->get(UserCreateService::class, [$user, $mailService]);
        $userCreateService->run();

```

@grozzzny
Copy link
Author

Thanks, @mkodummy.
I will test later.

@whisere
Copy link

whisere commented Jun 23, 2020

@mkodummy and @grozzzny Thanks, the last change works!

But I get this warning when login with github:

Please use the Authorization HTTP header instead as using the access_token query parameter is deprecated.

Depending on your API usage, we'll be sending you this email reminder on a monthly basis.

Visit https://developer.github.com/changes/2020-02-10-deprecating-auth-through-query-param for more information about suggested workarounds and removal dates.

@vinhhung1108
Copy link

Thanks so much @mkodummy and @grozzzny, it worked for me. I searched for a few hours to find this topic.

@dantart
Copy link

dantart commented Nov 11, 2020

this happened to me also ... and I reached this page ... why is not fixed in the official repo ?

@mj4444ru
Copy link

mj4444ru commented Apr 19, 2021

For PHP 7.4+

    'user' => [
        'class' => Da\User\Module::class,
        'controllerMap' => [
            'security' => [
                'class' => Da\User\Controller\SecurityController::class,
                'on beforeAuthenticate' =>
                    static fn (Da\User\Event\SocialNetworkAuthEvent $event) => $event->account->save(false),
            ],
        ],
        // ...
    ],

@Jonyx4
Copy link

Jonyx4 commented Jun 16, 2021

This solution worked like a charm!

For PHP 7.4+

    'user' => [
        'class' => Da\User\Module::class,
        'controllerMap' => [
            'security' => [
                'class' => Da\User\Controller\SecurityController::class,
                'on beforeAuthenticate' =>
                    static fn (Da\User\Event\SocialNetworkAuthEvent $event) => $event->account->save(false),
            ],
        ],
        // ...
    ],

@srakl
Copy link

srakl commented Jul 11, 2021

For PHP 7.4+

    'user' => [
        'class' => Da\User\Module::class,
        'controllerMap' => [
            'security' => [
                'class' => Da\User\Controller\SecurityController::class,
                'on beforeAuthenticate' =>
                    static fn (Da\User\Event\SocialNetworkAuthEvent $event) => $event->account->save(false),
            ],
        ],
        // ...
    ],

@Jonyx4 @mj4444ru

I added this in my main.php anything else to add? doesm't seem to work for me. new accounts not getting registered with social networks.

@srakl
Copy link

srakl commented Jul 12, 2021

@grozzzny i tried your steps, after i login with google, it redirects me to user/registration/connect&code=adssad how do i get it to skip that? and get fill in the firtsname lastname email etc from google

@Jonyx4
Copy link

Jonyx4 commented Jul 12, 2021

For PHP 7.4+

    'user' => [
        'class' => Da\User\Module::class,
        'controllerMap' => [
            'security' => [
                'class' => Da\User\Controller\SecurityController::class,
                'on beforeAuthenticate' =>
                    static fn (Da\User\Event\SocialNetworkAuthEvent $event) => $event->account->save(false),
            ],
        ],
        // ...
    ],

@Jonyx4 @mj4444ru

I added this in my main.php anything else to add? doesm't seem to work for me. new accounts not getting registered with social networks.

I don't know if this is related to your issue, but I also had to apply the fix described in this issue #397

@srakl
Copy link

srakl commented Jul 12, 2021

@Jonyx4 unfortunately adding the return $account; still redirects the user to user/registration/connect&code=adssad to confirm registration. it should auto fill in firstname lastname etc into db :(

@whisere
Copy link

whisere commented Jul 13, 2021

This works for me:

 'security' => [
                    'class' => 'Da\User\Controller\SecurityController',
                    'on beforeAuthenticate' => ['frontend\controllers\SocialNetworkHandler', 'beforeAuthenticate']
                ],

frontend\controllers\SocialNetworkHandler:

namespace frontend\controllers;

use Da\User\Event\SocialNetworkAuthEvent;
use Da\User\Factory\MailFactory;
use Da\User\Model\User;
use Da\User\Service\UserCreateService;
use Yii;
use yii\base\BaseObject;

class SocialNetworkHandler extends BaseObject
{
    /**
     * @param SocialNetworkAuthEvent $event
     */
    public static function beforeAuthenticate($event)
    {
        return $event->account->save(false);
    }
}

@srakl
Copy link

srakl commented Jul 13, 2021

@whisere does yours redirect newly registered users to the user/registration/connect page to input their email etc after they click on the social connect button? how do i bypass that step?

@whisere
Copy link

whisere commented Jul 13, 2021

It is normal that's just a step for user to confirm/edit their user name and email in the system (they may not want to use the same user name and email used in the social media account), it should automatically fill in the email address from social account.

@srakl
Copy link

srakl commented Jul 13, 2021

@whisere cool, thanks. if i was to skip that step, and auto fill firstname and last name from social account, know which file i can edit or extend by any chance?

@whisere
Copy link

whisere commented Jul 14, 2021

There may not be first and last name from social account, you can see:
https://github.com/2amigos/yii2-usuario/tree/master/src/User/AuthClient
(better to fork your own repo/copy if to make change to code)

overwriting controllers in the documentation:
https://yii2-usuario.readthedocs.io/en/latest/enhancing-and-overriding/overriding-controllers/#
and social events and other events under the events menu:
https://yii2-usuario.readthedocs.io/en/latest/events/social-network-connect-events/

@srakl
Copy link

srakl commented Jul 14, 2021

@whisere thanks. for the most part i got it working. It just doesn't seem to save the firstname and lastname in the user table. any idea what im missing here? here are the changes i made to the controller. #418

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants