Symfony2: how to log in using OAuth (HWIOAuthBundle) + custom roles (default and loaded from the database)

Note: the questions are at the end of this text, but I will explain in detail the whole context for a better understanding.

I am developing a Symfony2 application consisting of 3 modules:

  • Student module β†’ Role ROLE_STUDENT required
  • Teacher module β†’ Role ROLE_TEACHER required
  • Module for administrators β†’ Role_ADMIN required

Role hierarchy as follows:

  • ROLE_TEACHER: [ROLE_STUDENT]
  • ROLE_ADMIN: [ROLE_TEACHER]

In this way:

A student (with the role ROLE_STUDENT) can access only all pages of his module, for example:

The teacher (with the role ROLE_TEACHER) can access all pages of the student module and all pages of the teacher module, for example:

The administrator (with the role ROLE_ADMIN) can access all pages of the student module, all pages of the teacher module and the administrator backend.

The system uses OAuth to authenticate students and teachers via Twitter using the HWIOAuthBundle package (using the OAuthUserProvider provider that provides the package).

I have successfully authenticated users, but by default, all users are automatically authenticated using the following roles: [ROLE_USER, ROLE_OAUTH_USER]


So here is what I did. Below I will tell you that I want my application to be, but I do not know how to do it:

Steps to log in using OAuth:

The user is registered in the system and automatically:

  • If the user does not exist in the database:
    - Save the alias in the database user table.
    - Save the ROLE_STUDENT role (this is the default role for me) in the database user table.
    - Authentication in the system using OAuth, but using the ROLE_STUDENT role.

  • If the user exists in the database:
    - Check what role is associated with the user in the database.
    - User authentication on the system using OAuth, but using the role associated with the database (for example: ROLE_STUDENT or ROLE_TEACHER).

The administrator (from the administrator backend) can see the list of aliases (used by Twitter, but stored in the database) and the assigned roles for each alias. The administrator must be able to change the user role between ROLE_STUDENT and ROLE_TEACHER.


Questions:

  • How can I authenticate a user through OAuth (HWIOAuthBundle) with the role that I want by default (ROLE_STUDENT, as I explained above)?

  • If an alias exists in the database with the associated role (ROLE_STUDENT or ROLE_TEACHER), how can I authenticate the user through OAuth (HWIOAuthBundle), but using the role downloaded from the database?

I read a lot about this topic, but I'm new to Symfony2, and I don't know what is the best and easiest way to solve it.

Thank you in advance!

PS: if you have any questions or doubts, I will be happy to explain as best as possible.

+6
source share
1 answer

UPDATE:

I tried using this code in one of my recent projects, and it no longer worked. The reason is because HWIOAuthBundle has updated several times, and the configuration files do not match. I put the code above, and also registered on several other social networks on github, which you can find in HWIOAuthBundleByExample .


I have a week of experience with symfony2, and in recent days I have been working on myself. Found your question today (when I was still studying).

I am going to present to you what I needed to do based on the data and how I did it. After that, I will try to give you some key links, and I hope that you will be able to model them for your needs.

My apps need a Facebook account and an ADMIN role. Because there will be only a few administrators, I only need a few Facebook IDs for authentication, so I store them in a yaml array. (See At the end, how you can load them from the database).

Here is 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.url services: #here 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.yml security: providers: my_custom_hwi_provider: id: ib_user.oauth_user_provider access_control: - { path: ^/admin, roles: ROLE_SUPER_ADMIN } #app/parameters.yml parameters: #... facebook_client_id: ### facebook_client_secret: ### admins: - "my.facebook.id" #Acme\DemoBundle\Provider\Provider <?php namespace 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 <?php namespace 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 a request to enter facebook comes in, I do a database check (based on the facebook graph id) and add it if necessary. In addition, I set some things in the sessions (you won’t need it), and after that I also have to return the HWI \ Bundle \ OAuthBundle \ Security \ Core \ User \ OAuthUser object (this is where sf2 gets its roles). Therefore, I am expanding it (thus, I have access to $ isAdmin). As you said, you need roles for each user, and you must also edit them. To do this, you can implement getRoles () using ManyToMany relationships (provide access to the doctinary entityManager through the constructor). You can see what applies here: http://symfony.com/doc/current/cookbook/security/entity_provider.html#managing-roles-in-the-database .

As I said, you have to configure it a lot (my only application is to enter facebook only and with access as access in the form of help in_memory), but I would like for me to have such code when I started. So I really hope this helps you. Ask your questions, if any.

+10
source

Source: https://habr.com/ru/post/951854/


All Articles