OAuth HwioBundle, different socialNetWork

104 views Asked by At

I work to project in Symfony which have registration HWIOBundle for different social network. If user enters for example LinkedIn and some time for GitHub I has two user in database. Who knows how to do was one?

1

There are 1 answers

1
Mikhail Prosalov On BEST ANSWER

If user's email is similar in both social accounts, you can use email field to identify user. You should create user provider class. If user with provided social token won't be found in database, user provider will try to find user by email and add new social token for specified social network to existing user entity.

Code example.

services.xml

<service id="app.my_user_provider" class="AppBundle\Security\FOSUBUserProvider">
    <argument type="service" id="user_manager"/>
    <argument type="collection">
      <argument key="facebook">%facebook_id%</argument>
      <argument key="google">%google_id%</argument>
    </argument>
    <argument type="service" id="event_dispatcher"/>
</service>

security.yml, firewall section

    oauth:
        resource_owners:
            facebook: "/login/check-facebook"
            google: "/login/check-google"
        login_path: /login
        failure_path: /login

        oauth_user_provider:
            service: app.my_user_provider

src/AppBundle/Security/FOSUBUserProvider.php

<?php

namespace AppBundle\Security;

use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\User\UserInterface;

class FOSUBUserProvider extends BaseClass
{
    /**
     * {@inheritDoc}
     */
    public function connect(UserInterface $user, UserResponseInterface $response)
    {
        $username = $response->getUsername();

        $service = $response->getResourceOwner()->getName();
        $setter = 'set' . ucfirst($service);
        $setterId = $setter . 'Id';
        $setterToken = $setter . 'AccessToken';

        //disconnect previously connected user
        if (null !== $previousUser = $this->userManager->findUserBy(array($this->getProperty($response) => $username))) {
            $previousUser->$setterId(null);
            $previousUser->$setterToken(null);
            $this->userManager->updateUser($previousUser);
        }

        //connect current user
        $user->$setterId($username);
        $user->$setterToken($response->getAccessToken());

        $this->userManager->updateUser($user);
    }

    /**
     * {@inheritdoc}
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $username = $response->getUsername();
        $email = $response->getEmail();

        $user = $this->userManager->findUserBy(array($this->getProperty($response) => $username));
        if (null === $user) {
            $user = $this->userManager->findUserByEmail($email);

            $service = $response->getResourceOwner()->getName();
            $setter = 'set' . ucfirst($service);
            $setterId = $setter . 'Id';
            $setterToken = $setter . 'AccessToken';

            if (null === $user) {
                $user = $this->userManager->createUser();
                $user->$setterId($username);
                $user->$setterToken($response->getAccessToken());

                $user->setUsername($username);
                $user->setEmail($email);
                $user->setPassword($username);
                $user->setEnabled(true);
                $this->userManager->updateUser($user);

                return $user;
            } else {
                $user->$setterId($username);
                $user->$setterToken($response->getAccessToken());

                $this->userManager->updateUser($user);

                return $user;
            }
        }

        //if user exists - go with the HWIOAuth way
        $user = parent::loadUserByOAuthUserResponse($response);

        $serviceName = $response->getResourceOwner()->getName();
        $setter = 'set' . ucfirst($serviceName) . 'AccessToken';

        //update access token
        $user->$setter($response->getAccessToken());

        return $user;
    }
}