Symfony2: How to login using OAuth (HWIOAuthBundle) + custom roles (by default and loaded from DB) Symfony2: How to login using OAuth (HWIOAuthBundle) + custom roles (by default and loaded from DB) symfony symfony

Symfony2: How to login using OAuth (HWIOAuthBundle) + custom roles (by default and loaded from DB)


UPDATE:

I tried using this code in one of my recent projects and it didn't work anymore. The reason is that HWIOAuthBundle has updated a few times and the config files are not the same. I put the code above as well as login to a few other social networks in a github which you can find at HWIOAuthBundleByExample.


I have a week experience with symfony2 and in the past days that's what i was working myself. Found your question today (when i was still researching).

I'm gonna present you what I had to do, based on what data, and how i did it. After that, I'll try giving you some key links and I hope you'll manage to modelate for your needs.

My app needs Facebook login and ADMIN role. Because will only be a few administrators, I only need a few Facebook IDs when authentificating, so I store them in a yaml array. (See at the end how you can load them from database).

Here's what I did:

#/app/config.yml #the setup looks different (I need the picture and email credentials)hwi_oauth:  # name of the firewall in which this bundle is active, this setting MUST be set  firewall_name: secured_area  resource_owners:    facebook:      type:        facebook      client_id:       %facebook_client_id%      client_secret:     %facebook_client_secret%      scope:         "email"      infos_url:     "https://graph.facebook.com/me?fields=username,name,email,picture.type(square)"      paths:        email:          email        profilepicture: picture.data.urlservices: #here's where the magic happens  hwi_oauth.user.provider.entity:    class: HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider  ib_user.oauth_user_provider:    class: Acme\DemoBundle\Provider\Provider    arguments: [@session, @doctrine, %admins%]#app/security.ymlsecurity:  providers:    my_custom_hwi_provider:      id: ib_user.oauth_user_provider  access_control:        - { path: ^/admin, roles: ROLE_SUPER_ADMIN }#app/parameters.ymlparameters:  #...  facebook_client_id:     ###  facebook_client_secret: ###  admins:    - "my.facebook.id"#Acme\DemoBundle\Provider\Provider<?phpnamespace Acme\DemoBundle\Provider;use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider;use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;use Acme\DemoBundle\Entity\User;use Acme\DemoBundle\Provider\OAuthUser;class Provider extends OAuthUserProvider{    protected $session, $doctrine, $admins;    public function __construct($session, $doctrine, $admins) {        $this->session = $session;        $this->doctrine = $doctrine;        $this->admins = $admins;    }    public function loadUserByUsername($username)    {        return new OAuthUser($username, $this->isUserAdmin($username)); //look at the class below    }    private function isUserAdmin($nickname)    {        return in_array($nickname, $this->admins);    }    public function loadUserByOAuthUserResponse(UserResponseInterface $response)    {        //data from facebook response        $facebook_id = $response->getUsername();        $nickname = $response->getNickname();        $realname = $response->getRealName();        $email    = $response->getEmail();        $avatar   = $response->getProfilePicture();        //set data in session        $this->session->set('nickname', $nickname);        $this->session->set('realname', $realname);        $this->session->set('email', $email);        $this->session->set('avatar', $avatar);        //get user by fid        $qb = $this->doctrine->getManager()->createQueryBuilder();        $qb ->select('u.id')            ->from('AcmeDemoBundle:User', 'u')            ->where('u.fid = :fid')            ->setParameter('fid', $facebook_id)            ->setMaxResults(1);        $result = $qb->getQuery()->getResult();        //add to database if doesn't exists        if ( !count($result) ) {            $User = new User();            $User->setCreatedAt(new \DateTime());            $User->setNickname($nickname);            $User->setRealname($realname);            $User->setEmail($email);            $User->setAvatar($avatar);            $User->setFID($facebook_id);            $em = $this->doctrine->getManager();            $em->persist($User);            $id = $em->flush();        } else {            $id = $result[0]['id'];        }        //set id        $this->session->set('id', $id);        //@TODO: hmm : is admin        if ($this->isUserAdmin($nickname)) {            $this->session->set('is_admin', true);        }        //parent:: returned value        return $this->loadUserByUsername($response->getNickname());    }    public function supportsClass($class)    {        return $class === 'Acme\\DemoBundle\\Provider\\OAuthUser';    }}#Acme\DemoBundle\Provider\OAuthUser<?phpnamespace Acme\DemoBundle\Provider;use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUser as HWIOAuthUser;class OAuthUser extends HWIOAuthUser{    private $isAdmin = false;    public function __construct($username, $isAdmin = false)    {        parent::__construct($username);        $this->isAdmin = $isAdmin;    }    public function getRoles()    {        $roles = array('ROLE_USER', 'ROLE_OAUTH_USER');        if ($this->isAdmin) {            array_push($roles, 'ROLE_SUPER_ADMIN');        }        return $roles;    }}

So you can pretty much see that when facebook login response comes, I do the database checks (based on the facebook graph ID), and add it if needed. Also, I set some things in sessions (you won't need this), and after that I must also return a HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUser object (this is where the sf2 gets it's roles). So I extend it (in this way i have acces to $isAdmin). As you said, you need roles for each user and you must also edit them. For that, you can implement getRoles() with a ManyToMany relationship (give access to doctrine entityManager via constructor). You can see that applied here: http://symfony.com/doc/current/cookbook/security/entity_provider.html#managing-roles-in-the-database .

As I said, you must tweak it a lot (my only app is facebook-only login and with a in_memory like security access), but I wish myself I had a code like that when i started. So I really hope this hels you. Post your questions, if any.