├── .gitignore ├── composer.json ├── config ├── .gitkeep └── security.php ├── readme.md └── src ├── Authentication ├── AuthenticationManager.php └── Token │ └── LaravelToken.php ├── Authorization └── Voter │ └── AuthVoter.php ├── Facade.php ├── SecurityServiceProvider.php └── helpers.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "barryvdh/laravel-security", 3 | "description": "This packages integrates Symfony Security Core in Laravel, mainly to use the Voters to check acces to roles/objects.", 4 | "keywords": ["laravel", "security", "voters", "roles", "auth"], 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Barry vd. Heuvel", 9 | "email": "barryvdh@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.4.0", 14 | "illuminate/support": "^5.0|^6.0|^7.0|^8.0", 15 | "symfony/security-core": "~2.6|~3.0|~4.0|~5.0" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "Barryvdh\\Security\\": "src/" 20 | }, 21 | "files": [ 22 | "src/helpers.php" 23 | ] 24 | }, 25 | "extra": { 26 | "laravel": { 27 | "providers": [ 28 | "Barryvdh\\Security\\SecurityServiceProvider" 29 | ], 30 | "aliases": { 31 | "Security": "Barryvdh\\Security\\Facade" 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /config/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/barryvdh/laravel-security/c26c08308f7549e86fc231775acb49d5002e7375/config/.gitkeep -------------------------------------------------------------------------------- /config/security.php: -------------------------------------------------------------------------------- 1 | 'affirmative', 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Role Hierarchy 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Set which roles inherit from other roles. Example: 28 | | array( 29 | | 'ROLE_ADMIN' => array('ROLE_USER'), 30 | | 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH') 31 | | ) 32 | | 33 | */ 34 | 'role_hierarchy' => array(), 35 | 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | Voters 39 | |-------------------------------------------------------------------------- 40 | | 41 | | The voters listed here will be automatically added. 42 | | 43 | */ 44 | 'voters' => [ 45 | 'Barryvdh\Security\Authorization\Voter\AuthVoter', 46 | 'Symfony\Component\Security\Core\Authorization\Voter\RoleHierarchyVoter', 47 | ], 48 | ); 49 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Laravel Security Component 2 | 3 | ### Version 0.2.x@dev is for Laravel 5. Use 0.1.x for Laravel 4! 4 | 5 | This packages integrates Symfony Security Core in Laravel, mainly to use the Voters to check acces to roles/objects. See [Symfony Authorization](http://symfony.com/doc/current/components/security/authorization.html) 6 | 7 | 8 | ### Install 9 | Add this package to your composer.json and run `composer update` 10 | 11 | "barryvdh/laravel-security": "0.2.x@dev" 12 | 13 | After updating, add the ServiceProvider to ServiceProvider array in config/app.php 14 | 15 | 'Barryvdh\Security\SecurityServiceProvider' 16 | 17 | You can optionally add the Facade as well, to provide faster access to the Security component. 18 | 19 | 'Security' => 'Barryvdh\Security\Facade', 20 | 21 | 22 | ### Configure 23 | You can publish the config to change the strategy and add your own Role Hierarchy, to configure which roles inherit from each other. 24 | 25 | $ php artisan vendor:publish config 26 | 27 | //config/security.php 28 | 'role_hierarchy' => array( 29 | 'ROLE_ADMIN' => array('ROLE_USER'), 30 | 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH') 31 | ) 32 | 33 | ### Voters 34 | By default, only 2 Voters are included: 35 | - AuthVoter, check if a user is autenticated (`IS_AUTHENTICATED` or `AUTH`) 36 | - RoleHierarchyVoter: Check a user for a role, using the hierarchy in the config. (`ROLE_ADMIN`, `ROLE_EDITOR` etc) 37 | 38 | To use roles, add a function getRoles() to your User model, which returns an array of Role strings (Note: roles must begin with ROLE_) 39 | 40 | public function roles(){ 41 | return $this->belongsToMany('Role'); 42 | } 43 | public function getRoles(){ 44 | return $this->roles()->lists('name'); 45 | } 46 | 47 | You can add voters by adding them to the config. 48 | 49 | 'voters' => [ 50 | ... 51 | 'App\Security\MyVoter.php', 52 | ], 53 | 54 | You can also add voters by extending $app['security.voters'] or using the facade: 55 | 56 | Security::addVoter(new MyVoter()); 57 | 58 | Voters have to implement [VoterInterface](https://github.com/symfony/Security/blob/master/Core/Authorization/Voter/VoterInterface.php). 59 | You can define which attributes (ie. ROLE_ADMIN, IS_AUTHENTICATED, EDIT etc) and which objects the voter can handle. 60 | The voter will be called to vote on an attribute (and possibly an object) and allow, deny or abstain access. 61 | Based on the strategy, the final decision is made based on the votes. (By default, 1 allow is enough) 62 | 63 | You can access the User object with $token->getUser(); 64 | For an example, see the [Symfony Cookbook about Voters](http://symfony.com/doc/current/cookbook/security/voters.html) 65 | 66 | ### Checking access 67 | You can check access using to IoC Container, the facade and a helper function: 68 | 69 | App::make('security.authorization_checker')->isGranted('ROLE_ADMIN'); 70 | Security::isGranted('edit', $post); 71 | is_granted('AUTH'); 72 | 73 | The first argument is the attribute you want to check, the second is an optional object, on which you want to check the access. 74 | For example, you can write a Voter to check if the current user can edit a comment, based on his ownership on that object or his role. 75 | 76 | ### Filters 77 | You can use this in Laravel's Route Filters, both in the routes and in controllers. 78 | 79 | Route::get('admin', array('before' => 'is_granted:ROLE_ADMIN', function(){..})); 80 | Route::filter('is_granted', function($route, $request, $attribute, $parameter=null){ 81 | if (!is_granted($attribute, $route->getParameter($parameter))) 82 | return Redirect::route('login'); 83 | }); 84 | 85 | If you set up Model Binding, you have easy access to the objects. 86 | 87 | Route::model('company', 'Company'); 88 | Route::get('companies/{company}', array('uses'=> 'CompanyController@getView', 'before' => 'is_granted:view,company')); 89 | -------------------------------------------------------------------------------- /src/Authentication/AuthenticationManager.php: -------------------------------------------------------------------------------- 1 | getRoles()); 19 | }else{ 20 | parent::__construct(array()); 21 | } 22 | 23 | 24 | if(!is_null($user)){ 25 | $this->setUser($user); 26 | $this->setAuthenticated(true); 27 | }else{ 28 | $this->setUser(''); 29 | $this->setAuthenticated(false); 30 | } 31 | 32 | } 33 | 34 | 35 | public function getCredentials() 36 | { 37 | return ''; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/Authorization/Voter/AuthVoter.php: -------------------------------------------------------------------------------- 1 | supportsAttribute($attribute)) { 39 | continue; 40 | } 41 | 42 | $result = VoterInterface::ACCESS_DENIED; 43 | 44 | if ((self::IS_AUTHENTICATED === $attribute or self::AUTH === $attribute) && $token->isAuthenticated() ) { 45 | return VoterInterface::ACCESS_GRANTED; 46 | } 47 | 48 | } 49 | 50 | return $result; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Facade.php: -------------------------------------------------------------------------------- 1 | extend('security.voters', function($voters) use ($voter) { 13 | $voters[] = $voter; 14 | return $voters; 15 | }); 16 | } 17 | /** 18 | * {@inheritDoc} 19 | */ 20 | protected static function getFacadeAccessor() { return 'security.authorization_checker'; } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/SecurityServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 29 | __DIR__.'/../config/security.php' => config_path('security.php'), 30 | ], 'config'); 31 | } 32 | 33 | /** 34 | * Register the service provider. 35 | * 36 | * @return void 37 | */ 38 | public function register() 39 | { 40 | $this->mergeConfigFrom( 41 | __DIR__.'/../config/security.php', 'security' 42 | ); 43 | 44 | $app = $this->app; 45 | 46 | $app['security.role_hierarchy'] = $app['config']->get('security.role_hierarchy', array()); 47 | $app['security.strategy'] = $app['config']->get('security.strategy', 'affirmative'); 48 | 49 | $app->singleton('security', function ($app) { 50 | // Deprecated. Use security.authorization_checker instead. 51 | $security = new SecurityContext($app['security.authentication_manager'], $app['security.access_manager']); 52 | $security->setToken(new LaravelToken($app['auth']->user())); 53 | return $security; 54 | }); 55 | 56 | $app->singleton('security.token_storage', function($app) { 57 | $tokenStorage = new TokenStorage(); 58 | $tokenStorage->setToken(new LaravelToken($app['auth']->user())); 59 | return $tokenStorage; 60 | }); 61 | 62 | $app->singleton('security.authorization_checker', function ($app) { 63 | return new AuthorizationChecker($app['security.token_storage'], $app['security.authentication_manager'], $app['security.access_manager']); 64 | }); 65 | $app->alias('security.authorization_checker', 'Symfony\Component\Security\Core\Authorization\AuthorizationChecker'); 66 | 67 | $app->singleton('security.authentication_manager', function ($app) { 68 | return new AuthenticationManager(); 69 | }); 70 | 71 | $app->singleton('security.access_manager', function ($app) { 72 | return new AccessDecisionManager($app['security.voters'], $app['security.strategy']); 73 | }); 74 | 75 | $app->bind('Symfony\Component\Security\Core\Role\RoleHierarchyInterface', function($app) { 76 | return new RoleHierarchy($app['security.role_hierarchy']); 77 | }); 78 | 79 | $app->singleton('security.voters', function ($app) { 80 | return array_map(function($voter) use ($app) { 81 | return $app->make($voter); 82 | }, $app['config']->get('security.voters')); 83 | }); 84 | 85 | //Listener for Login event 86 | $app['events']->listen('auth.login', function($user) use($app){ 87 | $app['security.token_storage']->setToken(new LaravelToken($user)); 88 | }); 89 | 90 | $app['events']->listen('auth.logout', function() use($app){ 91 | $app['security.token_storage']->setToken(new LaravelToken(null)); 92 | }); 93 | } 94 | 95 | 96 | /** 97 | * Get the services provided by the provider. 98 | * 99 | * @return array 100 | */ 101 | public function provides() 102 | { 103 | return array('security', 'security.role_hierarchy' , 'security.authentication_manager', 'security.access_manager', 'security.voters', 'security.authorization_checker' ); 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/helpers.php: -------------------------------------------------------------------------------- 1 | isGranted($attributes, $object); 17 | } 18 | 19 | } 20 | --------------------------------------------------------------------------------