AOuth login can't store session token, but userdata is stored correctly in DB with HWIAOuthBundle

266 Views Asked by At

I am using HWIAOuthBundle and Custom UserProvider on Symfony 4.4

in MyUserProvider

It stored the access_token and create new user. It works successfully.

<?php

namespace App\Security;

use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\EntityUserProvider;
use Doctrine\ORM\EntityManagerInterface;

class MyUserProvider extends EntityUserProvider implements OAuthAwareUserProviderInterface
{
    private $entityManager;
    
    /**
     * {@inheritdoc}
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        $username = $response->getUsername();
        $email = $response->getEmail();
        $user = $this->em
            ->getRepository(\App\Entity\User::class)
            ->findOneByEmail($response->getEmail());
        //when the user is registrating
        if (null === $user) {
            $service = $response->getResourceOwner()->getName();
            $setter = 'set' . ucfirst($service);
            $setter_id = $setter . 'Id';
            $setter_token = $setter . 'AccessToken';
            // create new user here
            $user = new \App\Entity\User();
            $user->$setter_id($username);
            $user->$setter_token($response->getAccessToken());
            //I have set all requested data with the user's username
            //modify here with relevant data
            //   $user->setUsername($username);
            $user->setEmail($email);
            $user->setPassword($username);
            $user->setEnabled(true);
            $this->em->persist($user);
            $this->em->flush();

            //$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;
    }
}

However even the user is created correctly in Database, but not login-ed

$this->getUser(); in Controller returns null.

enter image description here

So, I am confused that where the user login accomplished???

my setting is below

security:
    firewalls:
        main:
            oauth:
                resource_owners:
                    facebook:            "/login/check-facebook"
                    google:              "/login/check-google"
                    twitter:             "/login/check-twitter"
                login_path:        /login
                use_forward:       false
     #          failure_path:      /login
                oauth_user_provider:
                    service: my.user.provider

services.yml

my.user.provider:
    class:        App\Security\MyUserProvider
    arguments: ['@doctrine', App\Entity\User , { facebook: facebook_id, twitter: twitter_id, google: google_id }]


hwi_oauth:
    resource_owners:
        facebook:
            type:           facebook
            client_id:      '%env(FB_ID)%'
            client_secret:  '%env(FB_SECRET)%'
            scope:          "email user_posts"
        google:
            type:                google
            client_id:           <client_id>
            client_secret:       <client_secret>
            scope:               "email profile"
        twitter:
            type:                twitter
            client_id:           XXXXXXX
            client_secret:       XXXXXX
            scope:               "email profile"

Additional

$token = $this->container->get('security.token_storage')->getToken();
var_dump($token);

There is only annonymous.

object(Symfony\Component\Security\Core\Authentication\Token\AnonymousToken)#664 (6) { ["secret":"Symfony\Component\Security\Core\Authentication\Token\AnonymousToken":private]=> string(7) "QZZau69" ["user":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=> string(5) "anon." ["roles":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=> array(0) { } ["roleNames":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=> array(0) { } ["authenticated":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=> bool(true) ["attributes":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=> array(0) { } }

So, I think MyUserProvider or somewhere( like AuthenticationListener??) else that should store the token failed.

1

There are 1 best solutions below

0
Cameron Hurd On

You may get some mileage out of reviewing your Custom UserProvider's refresh method.

That's how the token is reloaded & validated between requests in the same session. If you're extending EntityUserProvider, perhaps the logic doesn't match and refresh needs overriding, too.

<?php 

// https://github.com/hwi/HWIOAuthBundle/blob/7a13716e68faf185bd22aef20b37a523569f2ea3/Security/Core/User/EntityUserProvider.php

...

/**
 * {@inheritdoc}
 */
public function refreshUser(UserInterface $user)
{
    $accessor = PropertyAccess::createPropertyAccessor();
    $identifier = $this->properties['identifier'];
    if (!$accessor->isReadable($user, $identifier) || !$this->supportsClass(\get_class($user))) {
        throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', \get_class($user)));
    }

    $userId = $accessor->getValue($user, $identifier);
    $username = $user->getUsername();

    if (null === $user = $this->findUser([$identifier => $userId])) {
        $exception = new UsernameNotFoundException(sprintf('User with ID "%d" could not be reloaded.', $userId));
        $exception->setUsername($username);

        throw $exception;
    }

    return $user;
}

...