├── .editorconfig ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── laravel-authorize.php └── src ├── AuthorizeServiceProvider.php └── Middleware └── Authorize.php /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | indent_size = 4 9 | indent_style = space 10 | end_of_line = lf 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All Notable changes to `laravel-authorize` will be documented in this file 4 | 5 | ## 1.1.2 - 2016-10-31 6 | - Fixed the status code. It has been changed from 401 to 403. 7 | 8 | ## 1.1.1 - 2016-03-29 9 | - Fixed a bug the prevented the config file from being published 10 | 11 | ## 1.1.0 - 2016-03-29 12 | - Made the login route configurable 13 | 14 | ## 1.0.1 - 2015-09-23 15 | 16 | ### Fixed 17 | - Made examples, tests, readme more clear 18 | 19 | ## 1.0.0 - 2015-09-23 20 | 21 | ### Added 22 | - Initial release 23 | 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) Spatie bvba 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [](https://supportukrainenow.org) 3 | 4 | # A middleware to check authorization 5 | 6 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/laravel-authorize.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-authorize) 7 | [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) 8 | [![Build Status](https://img.shields.io/travis/spatie/laravel-authorize/master.svg?style=flat-square)](https://travis-ci.org/spatie/laravel-authorize) 9 | [![SensioLabsInsight](https://img.shields.io/sensiolabs/i/c6adf478-99b9-4a52-8635-881f6b66c8d3.svg?style=flat-square)](https://insight.sensiolabs.com/projects/c6adf478-99b9-4a52-8635-881f6b66c8d3) 10 | [![Quality Score](https://img.shields.io/scrutinizer/g/spatie/laravel-authorize.svg?style=flat-square)](https://scrutinizer-ci.com/g/spatie/laravel-authorize) 11 | [![StyleCI](https://styleci.io/repos/42896120/shield?branch=master)](https://styleci.io/repos/42896120) 12 | [![Total Downloads](https://img.shields.io/packagist/dt/spatie/laravel-authorize.svg?style=flat-square)](https://packagist.org/packages/spatie/laravel-authorize) 13 | 14 | This package provides a route middleware to protect routes from unauthorized access. It hooks into the authorization 15 | features that were [introduced in Laravel 5.1.11](http://laravel.com/docs/5.1/authorization). 16 | 17 | Protecting a route can be done by adding middleware to it: 18 | ```php 19 | Route::get('/top-secret-page', [ 20 | 'middleware' => 'can:viewTopSecretPage', 21 | 'uses' => 'TopSecretController@index', 22 | ]); 23 | ``` 24 | 25 | Of course this middleware can also be applied to a bunch of routes: 26 | 27 | ```php 28 | Route::group(['prefix' => 'admin', 'middleware' => 'can:viewAdmin'], function() { 29 | 30 | //all the controllers of your admin section 31 | ... 32 | 33 | }); 34 | ``` 35 | 36 | Furthermore the middleware can use [route model binding](https://laracasts.com/series/laravel-5-fundamentals/episodes/18): 37 | ```php 38 | Route::get('/post/{post}', [ 39 | 'middleware' => 'can:editPost,post', 40 | 'uses' => 'PostController@edit', 41 | ]); 42 | ``` 43 | 44 | Spatie is a webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource). 45 | 46 | ## Support us 47 | 48 | [](https://spatie.be/github-ad-click/laravel-authorize) 49 | 50 | We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). 51 | 52 | We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). 53 | 54 | ## Postcardware 55 | 56 | You're free to use this package (it's [MIT-licensed](LICENSE.md)), but if it makes it to your production environment you are required to send us a postcard from your hometown, mentioning which of our package(s) you are using. 57 | 58 | Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium. 59 | 60 | The best postcards will get published on the open source page on our website. 61 | 62 | ## Do not use in Laravel 5.2.28 and up 63 | 64 | Laravel 5.2.28 or higher contain the middleware this package provides [out of the box](https://github.com/laravel/framework/blob/v5.2.28/src/Illuminate/Foundation/Http/Middleware/Authorize.php). There's no need do install this package in those versions of Laravel. 65 | 66 | ## Install 67 | 68 | You can install the package via composer: 69 | ``` bash 70 | $ composer require spatie/laravel-authorize 71 | ``` 72 | 73 | Next, you must install the service provider: 74 | 75 | ```php 76 | // config/app.php 77 | 'providers' => [ 78 | ... 79 | Spatie\Authorize\AuthorizeServiceProvider::class, 80 | ]; 81 | ``` 82 | 83 | Next, the `\Spatie\Authorize\Middleware\Authorize::class`-middleware must be registered in the kernel: 84 | 85 | ```php 86 | //app/Http/Kernel.php 87 | 88 | protected $routeMiddleware = [ 89 | ... 90 | 'can' => \Spatie\Authorize\Middleware\Authorize::class, 91 | ]; 92 | ``` 93 | 94 | Naming the middleware `can` is just a suggestion. You can give it any name you'd like. 95 | 96 | The `authorize`-middleware includes all functionality provided by the standard `auth`-middleware. So you could 97 | also opt to replace the `App\Http\Middleware\Authenticate`-middleware by `Spatie\Authorize\Middleware\Authorize`: 98 | 99 | ```php 100 | //app/Http/Kernel.php 101 | 102 | protected $routeMiddleware = [ 103 | 'auth' => 'Spatie\Authorize\Middleware\Authorize', 104 | ... 105 | ]; 106 | ``` 107 | 108 | You can publish the config-file with: 109 | ```bash 110 | php artisan vendor:publish --provider="Spatie\Authorize\AuthorizeServiceProvider" 111 | ``` 112 | 113 | This is the contents of the published config file: 114 | 115 | ```php 116 | return [ 117 | /* 118 | * The path to redirect for login. 119 | */ 120 | 'login_url' => 'auth/login' 121 | ]; 122 | ``` 123 | 124 | ## Usage 125 | 126 | ### Checking authentication 127 | When the middleware is used without any parameters at all, it will only allow logged in users to use the route. 128 | If you plan on using the middleware like this I recommend that you replace the standard `auth`-middleware with the one 129 | provided by this package. 130 | 131 | ```php 132 | //only logged in users will be able to see this 133 | 134 | Route::get('/top-secret-page', ['middleware' => 'auth', 'uses' => 'TopSecretController@index']); 135 | ``` 136 | 137 | ### Checking authorization 138 | The middleware accepts the name of an ability you have defined as the first parameter: 139 | 140 | ```php 141 | //only users with the viewTopSecretPage-ability be able to see this 142 | 143 | Route::get('/top-secret-page', [ 144 | 'middleware' => 'can:viewTopSecretPage', 145 | 'uses' => 'TopSecretController@index', 146 | ]); 147 | ``` 148 | 149 | ### Using form model binding 150 | Image you've set up an ability like this: 151 | 152 | ```php 153 | //inside the boot method of AuthServiceProvider 154 | 155 | $gate->define('update-post', function ($user, $post) { 156 | return $user->id === $post->user_id; 157 | }); 158 | ``` 159 | 160 | The middleware accepts the name of a bound model as the second parameter. 161 | 162 | ```php 163 | Route::get('/post/{post}', [ 164 | 'middleware' => 'can:editPost,post', 165 | 'uses' => 'PostController@edit', 166 | ]); 167 | ``` 168 | 169 | Behind the scene the middleware will pass the model bound that is bound to the round to 170 | the defined `update-post`-ability. 171 | 172 | ## What happens with unauthorized requests? 173 | 174 | ### Default behaviour 175 | 176 | This is the default behaviour defined in the middleware. 177 | 178 | ```php 179 | use Symfony\Component\HttpKernel\Exception\HttpException; 180 | ... 181 | 182 | protected function handleUnauthorizedRequest($request, $ability = null, $model = null) 183 | { 184 | if ($request->ajax()) { 185 | return response('Unauthorized.', Response::HTTP_UNAUTHORIZED); 186 | } 187 | 188 | if (!$request->user()) { 189 | return redirect()->guest(config('laravel-authorize.login_url')); 190 | } 191 | 192 | throw new HttpException(Response::HTTP_UNAUTHORIZED, 'This action is unauthorized.'); 193 | } 194 | ``` 195 | 196 | So guests will get redirected to the default login page, logged in users will get a response 197 | with status `HTTP_UNAUTHORIZED` aka 401. 198 | 199 | ### Custom behaviour 200 | 201 | To customize the default behaviour you can easily extend the default middleware and 202 | override the `handleUnauthorizedRequest`-method. Don't forget to register your class at the kernel. 203 | 204 | If you would like to let all unauthorized users know that you are actually a teapot you can do so. 205 | 206 | ```php 207 | //app/Http/Middleware/Authorize.php 208 | 209 | namespace App\Http\Middleware; 210 | 211 | use Spatie\Authorize\Middleware\Authorize as BaseAuthorize; 212 | use Symfony\Component\HttpFoundation\Response; 213 | 214 | class Authorize extends BaseAuthorize 215 | { 216 | protected function handleUnauthorizedRequest($request, $ability = null, $model = null) 217 | { 218 | return reponse('I am a teapot.', Response::HTTP_I_AM_A_TEAPOT); 219 | } 220 | } 221 | ``` 222 | 223 | In the kernel: 224 | 225 | ```php 226 | //app/Http/Kernel.php 227 | 228 | protected $routeMiddleware = [ 229 | 'can' => 'App\Http\Middleware\Authorize', 230 | ... 231 | ]; 232 | ``` 233 | 234 | ## Change log 235 | 236 | Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. 237 | 238 | ## Testing 239 | 240 | This package contains integration tests that are powered by [orchestral/testbench](https://github.com/orchestral/testbench). 241 | 242 | You can run all tests with: 243 | ``` bash 244 | $ composer test 245 | ``` 246 | 247 | ## Contributing 248 | 249 | Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. 250 | 251 | ## Security 252 | 253 | If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker. 254 | 255 | ## Credits 256 | 257 | - [Freek Van der Herten](https://github.com/freekmurze) 258 | - [All Contributors](../../contributors) 259 | 260 | A big thank you to [Joseph Silber](https://github.com/JosephSilber) for all the excellent feedback he gave 261 | while this package was being created. 262 | 263 | ## About Spatie 264 | Spatie is webdesign agency in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource). 265 | 266 | ## License 267 | 268 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 269 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spatie/laravel-authorize", 3 | "description": "A middleware to check authorization", 4 | "keywords": [ 5 | "spatie", 6 | "laravel-authorize", 7 | "route", 8 | "middleware", 9 | "authorization", 10 | "laravel" 11 | ], 12 | "homepage": "https://github.com/spatie/laravel-authorize", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Freek Van der Herten", 17 | "email": "freek@spatie.be", 18 | "homepage": "https://spatie.be", 19 | "role": "Developer" 20 | } 21 | ], 22 | "require": { 23 | "php" : ">=5.5.0", 24 | "laravel/framework": "~5.1.11|~5.2.0 < 5.2.28", 25 | "illuminate/contracts": "~5.1.11|~5.2.0" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit" : "4.*", 29 | "scrutinizer/ocular": "~1.1", 30 | "orchestra/testbench": "~3.1.0|~3.2.0" 31 | }, 32 | "autoload": { 33 | "psr-4": { 34 | "Spatie\\Authorize\\": "src" 35 | } 36 | }, 37 | "autoload-dev": { 38 | "psr-4": { 39 | "Spatie\\Authorize\\Test\\": "tests" 40 | } 41 | }, 42 | "scripts": { 43 | "test": "vendor/bin/phpunit" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /config/laravel-authorize.php: -------------------------------------------------------------------------------- 1 | 'auth/login', 8 | ]; 9 | -------------------------------------------------------------------------------- /src/AuthorizeServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 22 | __DIR__.'/../config/laravel-authorize.php' => config_path('laravel-authorize.php'), 23 | ]); 24 | } 25 | 26 | /** 27 | * Register the service provider. 28 | */ 29 | public function register() 30 | { 31 | $this->mergeConfigFrom(__DIR__.'/../config/laravel-authorize.php', 'laravel-authorize'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Middleware/Authorize.php: -------------------------------------------------------------------------------- 1 | getModelFromRequest($request, $boundModelName); 26 | 27 | if (!$this->hasRequiredAbility($request->user(), $ability, $model)) { 28 | return $this->handleUnauthorizedRequest($request, $ability, $model); 29 | } 30 | 31 | return $next($request); 32 | } 33 | 34 | /** 35 | * Get the model from the request using given boundModelName. 36 | * 37 | * @param mixed $request 38 | * @param string $boundModelName 39 | * 40 | * @return \Illuminate\Database\Eloquent\Model|null 41 | */ 42 | protected function getModelFromRequest($request, $boundModelName) 43 | { 44 | if (is_null($boundModelName)) { 45 | return; 46 | } 47 | 48 | return $request->route($boundModelName); 49 | } 50 | 51 | /** 52 | * Determine if the currently logged in use has the given ability. 53 | * 54 | * @param $user 55 | * @param string|null $ability 56 | * @param \Illuminate\Database\Eloquent\Model|null $model 57 | * 58 | * @return bool 59 | */ 60 | protected function hasRequiredAbility($user, $ability = null, $model = null) 61 | { 62 | if (!$user) { 63 | return false; 64 | } 65 | 66 | if (is_null($ability)) { 67 | return true; 68 | } 69 | 70 | /* 71 | * Some gates may check on number of arguments given. If model 72 | * is null, don't pass it as an argument. 73 | */ 74 | if (is_null($model)) { 75 | return $user->can($ability); 76 | } 77 | 78 | return $user->can($ability, $model); 79 | } 80 | 81 | /** 82 | * Handle the unauthorized request. 83 | * 84 | * @param $request 85 | * @param string|null $ability 86 | * @param \Illuminate\Database\Eloquent\Model|null $model 87 | * 88 | * @throws \Symfony\Component\HttpKernel\Exception\HttpException 89 | * 90 | * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\RedirectResponse|Response 91 | */ 92 | protected function handleUnauthorizedRequest($request, $ability = null, $model = null) 93 | { 94 | if ($request->ajax()) { 95 | return response('Forbidden.', Response::HTTP_FORBIDDEN); 96 | } 97 | 98 | if (!$request->user()) { 99 | return redirect()->guest(config('laravel-authorize.login_url')); 100 | } 101 | 102 | throw new HttpException(Response::HTTP_UNAUTHORIZED, 'This action is unauthorized.'); 103 | } 104 | } 105 | --------------------------------------------------------------------------------