pheonix/service-voter

Pheonix service voter allows to validate priviledges and authorization of Pheonix Micro services


Keywords
package, security, composer
License
MIT

Documentation

Introduction

Access Voter (wk-phx-access-voter) is a PHP package for validating privileges and steward within Phoenix Microservices.

Access Voter uses symfony/security package to get security annotations and their parameters within the library.

Requires:

  • “php”:”^7.2”
  • sensio/framework-extra-bundle: ^5.1
  • symfony/security-bundle: ^4.3
  • symfony/security: ^4.3
  • symfony/expression-language: ^4.3
  • symfony/http-foundation: ^4.0

Auth API will pass privilege access and steward access at the header, to retrieve from the header parameter and validate as per resource actions and requested action, using symfony/http-foundation to get the \Request object.

Symfony Docs

The @Security and @IsGranted annotations restrict access on controllers:

/**  
*  @Security(
*  "is_granted('attribute',  'subject')  and  is_granted('attribute',  'subject') …",  
*  statusCode='401',  
*  message='Do  not  have  permission')  
*/

Header Parameters

To use Access voter expected header parameters.

  • pvg - used to validate privilege level access
  • std - used to validate steward level access

Installation

In applications using Symfony Voter, run this command to install the Phx access voter based security annotation before using it:

composer require wk-phx/access-voter

Dependency

While installing phx/access-voter all dependency packages will be installed automatically.

  1. symfony/http-foundation
    Access voter needs \RequestStack object to get Current Request, with the help of \Request object we can get header and query parameters.

    Symfony\Component\HttpFoundation\RequestStack; Symfony\Component\HttpFoundation\Request;

  2. symfony/security
    Access voter needs \Voter to get security annotation’s attributes and subject.

    Symfony\Component\Security\Core\Authorization\Voter\Voter; Symfony\Component\Security\Core\Authentication\Token\TokenInterface

Privilege Validation

use @Security and @IsGranted library at the top of the controller, after adding security annotation for the privilege as the subject with their attribute.

src/Modules/Asset/AssetController.php

use  Sensio\Bundle\FrameworkExtraBundle\Configuration\{  
	Security,  
	IsGranted  
};  
class  AssetController  extends  Controller  
{  
	/**  
	* @Security(  
	* "is_granted('cr', 'privilege'))",  
	* statusCode='401',  
	* message='Do not have permission'  
	* )  
	*/  
	public  function  create()  
	{  
		// ...  
	}  
}

To use Access Voter and extend the class within microservice, we need to create a class.

To extend the feature of Access Voter library, we have to pass within constructor required parameters

  • resourceName (Required)
    is the name of the microservice.
  • \RequestStack (Required)
    is allowed access voter to get request object of the method.
  • \StewardInterface
    is required only if we wanted to implement steward validation within microservice.

Path of the class can be src/Security/ .

src/Security/AssetVoter.php

namespace  App\Security;  
use  Symfony\Component\DependencyInjection\ContainerInterface;  
use  Symfony\Component\HttpFoundation\RequestStack;  
use  Wk\Phx\Security\AccessVoter;  
  
/**  
* Middle ware class to validate Role permissions for Assets  
* @package Asset  
*/  
class  AssetVoter  extends  AccessVoter  
{  
	/**  
	* Asset voter construct  
	* @param ContainerInterface $container  
	* @param RequestStack $requestStack  
	*/  
	public  function  __construct(ContainerInterface $container, RequestStack $requestStack)  
	{  
		$resourceName = $container->getParameter('RESOURCE_NAME');
		// resourceName => Asset Manager  
		parent::__construct($resourceName, $requestStack);  
	}  
  
}

To execute that created class we need to define directory path within config/service.yaml

config/service.yaml

App\Security\:  
resource: '../src/Security/*'  
public: true

Steward Pre Validate and Steward Filter

To use steward-pre-validate or steward-filter with should implement the first Wk\Phx\Security\Dependency\StewardInterface.

NOTE: without implementing if we are passing steward-pre-validate or steward-filter it will return 401 - Do not have permission

src/Modules/Steward/StewardInterceptor.php

namespace  App\Modules\Steward;  
  
use  Symfony\Component\DependencyInjection\ContainerInterface;  
use  Symfony\Component\HttpFoundation\Request;  
use  Wk\Phx\Security\Dependency\StewardInterface;  
/**  
* Description of StewardInterceptor  
*/  
class  StewardInterceptor  implements  StewardInterface  
{  
	/**  
	* @var string  
	*/  
	const ALLOWED_STEWARD_IDS = 'allowedStewardIds';  
	  
	/**  
	* Using request object get resource identifier assetId and returns stewardId  
	* @param Request $reuqest  
	* @return string  
	*/  
	public  function  getStewardId(Request $reuqest): string  
	{  
		$assetId = $reuqest->get('assetId');
		// return stewardId by Asset Id
		return $this->repository->getStewardByAssetId($assetId);  
	}  
	  
	/**  
	* returns StewardId from Payload using request object  
	* @param Request $request  
	* @return string  
	*/  
	public  function  getStewardIdFromPayload(Request $request): string  
	{  
		$bodyContentArray = json_decode($request->getContent(), true);  
		// find if stewardId key is available in $bodyContentPayload  
		return $bodyContentArray[‘stewardId’];  
	}  
	  
	/**  
	* setting allowed steward ids to query parameter which we can use within DTO to pass SQL Query  
	* @param Request $request  
	* @param string $allowedStewardIds  
	*/  
	public  function  setAllowedStewardIds(Request $request, string $allowedStewardIds)  
	{  
		$request->query->set(self::ALLOWED_STEWARD_IDS, $allowedStewardIds);  
		return $request;  
	}  
  
}

After implementing the StewardInterface we should define the alias to access the class through the interface.

config/service.yaml

Wk\Phx\Security\Dependency\StewardInterface:  '@App\Modules\Steward\StewardInterceptor'

use @Security and @IsGranted library at the top of the controller, after adding security annotation for the steward-pre-validate or steward-filter as the subject with their attribute.

src/Modules/Asset/AssetController.php

use  Sensio\Bundle\FrameworkExtraBundle\Configuration\{  
	Security,  
	IsGranted  
};  
  
class  AssetController  extends  Controller  
{  
    // Constant variables to access inside security annotation block
    const SECURITY_ANNOTATION_STATUS_CODE = 401;
    const SECURITY_ANNOTATION_STATUS_MESSAGE = "Do not have permission";
	/**  
	* @Security(  
	* "is_granted('cr', 'privilege') and is_granted('cr', 'steward-pre-validate')",  
	*  statusCode=AssetController::SECURITY_ANNOTATION_STATUS_CODE, 
    *  message=AssetController::SECURITY_ANNOTATION_STATUS_MESSAGE
	* )  
	*/  
	public  function  create(Request $request)  
	{  
		// ...  
	}  
}

src/Security/AssetVoter.php

namespace  App\Security;  
     
   use  Symfony\Component\DependencyInjection\ContainerInterface;  
   use  Symfony\Component\HttpFoundation\RequestStack;  
   use  Wk\Phx\Security\AccessVoter;  
   use   Wk\Phx\Security\Dependency\StewardInterface;  
     
   /**  
   * Middle ware class to validate Role permissions for Assets  
   * @package Asset  
   */  
   class  AssetVoter  extends  AccessVoter  
   {  
   	/**  
   	* Asset voter construct  
   	* @param ContainerInterface $container  
   	* @param RequestStack $requestStack  
   	* @param StewardInterface $steward  
   	*/  
   	public  function  __construct(ContainerInterface $container, RequestStack $requestStack, StewardInterface $steward)  
   	{  
   		$resourceName = $container->getParameter('RESOURCE_NAME');
   		// Asset Manager  
   		parent::__construct($resourceName, $requestStack, $steward);  
   	}  
     
   }  

Uninstallation

To remove access-voter, can use below command

composer remove wk-phx/access-voter

Reference