How to differentiate between Symfony user roles/groups in socket.io chat How to differentiate between Symfony user roles/groups in socket.io chat php php

How to differentiate between Symfony user roles/groups in socket.io chat


I usually create a SecurityAccessManager service to check user's roles with voters calls (I can provide an exemple if needed) to check specific rights like "is this user can update this specific post?"

Config

company.navigation.security_access:    class: Company\NavigationBundle\Services\SecurityAccessManager    arguments:         - @security.authorization_checker                    - @security.token_storage

Service code

namespace Company\NavigationBundle\Services;use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;use Symfony\Component\Security\Core\Exception\AccessDeniedException;class SecurityAccessManager{    private $authorizationChecker;    private $tokenStorage;    private $debug;    public function __construct(            AuthorizationCheckerInterface $authorizationChecker,            TokenStorage $tokenStorage)    {              $this->authorizationChecker = $authorizationChecker;        $this->tokenStorage = $tokenStorage;           $this->debug = true;    }    // *************************************************************************    // User    // *************************************************************************    public function getUser()    {        return $this->tokenStorage->getToken()->getUser();            }    public function getUserId()    {        return $this->tokenStorage->getToken()->getUser()->getId();            }    public function isAuthenticatedUser()    {           return $this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED');    }         // *************************************************************************    // Roles checker    // *************************************************************************    public function isAdmin()    {        if($this->authorizationChecker->isGranted('ROLE_ADMIN') !== true) {            return false;        } else {            return true;                   }    }        public function checkRightAdmin()    {        if($this->authorizationChecker->isGranted('ROLE_ADMIN') !== true) {            throw new AccessDeniedException('Unauthorised access! '.($this->debug ? __FUNCTION__ : null));        }        return true;               }       public function checkUserHasRightToEditPost($postId)    {        // Check if user has right to modify the post        if ($this->authorizationChecker->isGranted('is_user_has_right_to_edit_post', $postId) === false) {            throw new AccessDeniedException('Unauthorised access! '.($this->debug ? __FUNCTION__ : null));        }        return true;    }  }

Then, in your controllers actions, you can check the user's rights

namespace Company\YourBundle\Controller;use Symfony\Bundle\FrameworkBundle\Controller\Controller;class YourBunbleController extends Controller{       /**     * Get the service     * @return \Company\NavigationBundle\Services\SecurityAccessManager     */    private function getService()    {                return $this->get('company.navigation.security_access');    }      public function updatePostAction(Request $request, $postId)    {           // Throw 403 if user has no admin rights        $this->getService()->checkRightAdmin();        // Throw 403 if user has no rights to update the post        $this->getService()->checkUserHasRightToEditPost();        //OK, you can update database        ...    }}


I had an idea of simply encrypting and sending the user's data to the node server, then decrypt it there. Only the two servers know the private keys, so even if a client gets its hands on the encrypted data, he can't make a request with it for another client.

That's the basic idea.

How I would do it?I would use something like JWT to just send the userId to the node application. Doesn't have to be encrypted, because I only care about the jwt signature to make sure the request was indeed issued by the real user.

After that, using the userId I would make a server side call to the php application to check the roles of the user.

To elaborate:

  • The node app and the php app will use a shared secret to sign the JWT token.
  • The PHP application will expose the generated token to the frontend.
  • The socket.io client will send the token as part of the authentication to the node app.

How to handle banning

  • keep a list of opened sockets with their user id
  • create a webservice endpoint in the nodejs application which can hanlde the "ban" requests from the php application.
  • when such a request is received by the nodejs application, lookup the socket based on the userid and close the connection.