Browse Source

Resolve all issues identified by phan

master
Adam Pippin 3 years ago
parent
commit
51e05643fd
  1. 5
      .phan/config.php
  2. 6
      .phan/stubs/Auth.php
  3. 3
      .phan/stubs/Cache.php
  4. 3
      .phan/stubs/Route.php
  5. 3
      .phan/stubs/Session.php
  6. 3
      .phan/stubs/Storage.php
  7. 4
      composer.json
  8. 10
      examples/custom/composer.lock
  9. 73
      src/Authkit2.php
  10. 35
      src/Http/Controllers/AuthenticationController.php
  11. 20
      src/Models/Token.php
  12. 62
      src/Observers/UserObserver.php
  13. 19
      src/Oidc/Authentication/Authentication.php
  14. 6
      src/Oidc/Authentication/ClientAuthentication.php
  15. 15
      src/Oidc/Authentication/TokenAuthentication.php
  16. 66
      src/Oidc/Client.php
  17. 1
      src/Oidc/Flows/ServiceAccountFlow.php
  18. 3
      src/Oidc/Flows/UserFlow.php
  19. 46
      src/Oidc/Token.php
  20. 3
      src/Providers/Authkit2ServiceProvider.php
  21. 9
      src/Providers/AuthnServiceProvider.php
  22. 10
      src/Providers/AuthzServiceProvider.php

5
.phan/config.php

@ -10,7 +10,10 @@ return [
'src/',
'vendor/laravel/',
'vendor/composer/',
'vendor/symfony/'
'vendor/symfony/',
'vendor/guzzlehttp/',
'vendor/psr/',
'vendor/firebase/'
],
'exclude_analysis_directory_list' => [

6
.phan/stubs/Auth.php

@ -1,7 +1,3 @@
<?php
/**
* @method static mixed loginUsingId(mixed $id)
* @method static void login(mixed $user)
*/
class Auth {}
class Auth extends \Illuminate\Support\Facades\App {}

3
.phan/stubs/Cache.php

@ -0,0 +1,3 @@
<?php
class Cache extends \Illuminate\Support\Facades\Cache {}

3
.phan/stubs/Route.php

@ -0,0 +1,3 @@
<?php
class Route extends \Illuminate\Support\Facades\Route {}

3
.phan/stubs/Session.php

@ -0,0 +1,3 @@
<?php
class Session extends \Illuminate\Support\Facades\Session {}

3
.phan/stubs/Storage.php

@ -0,0 +1,3 @@
<?php
class Storage extends \Illuminate\Support\Facades\Storage {}

4
composer.json

@ -31,5 +31,9 @@
"friendsofphp/php-cs-fixer": "^2.18",
"phan/phan": "^4.0",
"laravel/framework": "^8.31"
},
"scripts": {
"analyze": "phan",
"format": "php-cs-fixer fix --allow-risky=yes"
}
}

10
examples/custom/composer.lock

@ -12,7 +12,7 @@
"dist": {
"type": "path",
"url": "../..",
"reference": "aea8352e39283f5c1a8d4a3f9089ee101f3efcbe"
"reference": "2745fdc84ef4fa8d1ed834ba8bec761740b2f1d7"
},
"require": {
"firebase/php-jwt": "^5.2",
@ -37,6 +37,14 @@
"authkit2\\": "src"
}
},
"scripts": {
"analyze": [
"phan"
],
"format": [
"php-cs-fixer fix --allow-risky=yes"
]
},
"license": [
"proprietary"
],

73
src/Authkit2.php

@ -3,8 +3,8 @@
namespace authkit2;
/**
* Internal class for providing a single interface integrating with native PHP,
* Laravel, and any other environment we need to support.
* Helper class to abstract away the framework authkit2 is running on as well
* as provide simple helper methods for using it outside of a framework.
*
* @method static mixed cache(string $key, callable $generator)
* @method static mixed cache_get(string $key, mixed $default = null)
@ -179,10 +179,36 @@ class Authkit2
protected function getLaravelCallbacks(): array
{
return [
'session_get' => function(string $key) { return \Session::get($key); },
'session_set' => function(string $key, $value) { \Session::put($key, $value); },
'cache_get' => function(string $key) { return \Cache::get($key); },
'cache_set' => function(string $key, $value) { \Cache::set($key, $value); }
'session_get' =>
/**
* Fetch a variable from the session
* @param string $key
* @return mixed
*/
function(string $key) { return \Session::get($key); },
'session_set' =>
/**
* Set a variable in the session
* @param string $key
* @param mixed $value
* @return void
*/
function(string $key, $value): void { \Session::put($key, $value); },
'cache_get' =>
/**
* Fetch a value from cache
* @param string $key
* @return mixed
*/
function(string $key) { return \Cache::get($key); },
'cache_set' =>
/**
* Set a value in cache
* @param string $key
* @param mixed $value
* @return void
*/
function(string $key, $value): void { \Cache::set($key, $value); }
];
}
@ -250,22 +276,55 @@ class Authkit2
{
}
/**
* Configure the authkit2 library
*
* @param string $client_id
* @param string $client_secret
* @param string $endpoint
* @return void
*/
protected function ak2_configure(string $client_id, string $client_secret, string $endpoint): void
{
$this->client = new \authkit2\Oidc\Client($endpoint, $client_id, $client_secret);
}
/**
* Fetch a OIDC client authenticated as this application
*
* @return Oidc\Client
*/
protected function ak2_get_client(): Oidc\Client
{
return $this->client;
}
/**
* Given the essential values from a token (access token, refresh token),
* convert that into a Token object that can be used to make and authenticate
* requests.
*
* The refresh token is not strictly required, however if the token is
* expired then requests will simply fail. This use case is intended for
* authenticating requests using tokens other applications have sent to us.
*
* @param string $access_token
* @param ?string $refresh_token
* @return Oidc\Token
*/
protected function ak2_get_token(string $access_token, ?string $refresh_token = null): Oidc\Token
{
return Oidc\Token::fromString($this->client, $access_token, $refresh_token);
}
protected function ak2_refresh_token(Oidc\Token $token): Token
/**
* Refresh a token object -- generate a new access token from its
* refresh_token.
*
* @param Oidc\Token $token
* @return Oidc\Token a newly generated token
*/
protected function ak2_refresh_token(Oidc\Token $token): Oidc\Token
{
return $this->client->refreshToken($token);
}

35
src/Http/Controllers/AuthenticationController.php

@ -11,6 +11,10 @@ use authkit2\Models\Token;
*/
class AuthenticationController extends Controller
{
/**
* OIDC flow to mediate the actual login process and exchanges
* @var \authkit2\Oidc\Flows\UserFlow
*/
protected $user_flow;
public function __construct(\authkit2\Oidc\Flows\UserFlow $user_flow)
@ -44,7 +48,7 @@ class AuthenticationController extends Controller
*/
public function callback(Request $request)
{
$user_class = config('auth.providers.users.model');
$user_class = (string)config('auth.providers.users.model');
// Verify the passed in state value
$this->user_flow->validateState($request->state);
@ -86,17 +90,36 @@ class AuthenticationController extends Controller
}
}
// TODO: Log a useful error message in these cases
if (!isset($user))
{
// TODO: Log a useful error message
abort(500);
die();
}
else if (!method_exists($user, 'save'))
{
abort(500);
die();
}
else if (!method_exists($user, 'getAuthIdentifierName'))
{
abort(500);
die();
}
$token = new Token();
$token->id = $oidc_token->getUserId();
$token->access_token = $oidc_token->getAccessToken();
$token->refresh_token = $oidc_token->getRefreshToken();
$refresh_token = $oidc_token->getRefreshToken();
if (!isset($refresh_token))
{
abort(500);
die();
}
$token->refresh_token = $refresh_token;
// @phan-suppress-next-line PhanNonClassMethodCall
$token->user_id = $user->{$user->getAuthIdentifierName()};
// @phan-suppress-next-line PhanNonClassMethodCall
$token->save();
}
else
@ -109,10 +132,16 @@ class AuthenticationController extends Controller
$login_event_result = event(new \authkit2\Events\UserLogin($user, $user_info));
if (!sizeof($login_event_result))
{
if (!isset($user) || !method_exists($user, 'save'))
{
// TODO: Log a useful error message
abort(500);
}
// If nothing handled the login event, assume we're using laravel default
// everything and just go ahead and update the name/email
$user->name = $user_info['name'];
$user->email = $user_info['email'];
// @phan-suppress-next-line PhanNonClassMethodCall
$user->save();
}

20
src/Models/Token.php

@ -7,14 +7,26 @@ use \Illuminate\Database\Eloquent\Model;
/**
* User's OIDC token
*
* @property string id
* @property int user_id
* @property string access_token
* @property string refresh_token
* @property string $id
* @property int $user_id
* @property string $access_token
* @property string $refresh_token
*/
class Token extends Model
{
/**
* Override the default generated table name so we can namespace this and
* avoid conflicting with anything the app might already be using.
*
* @var string
*/
protected $table = 'authkit2_token';
/**
* Disable Eloquent's default created/updated fields
*
* @var bool
*/
public $timestamps = false;
}

62
src/Observers/UserObserver.php

@ -4,15 +4,30 @@ namespace authkit2\Observers;
use authkit2\Authkit2;
use authkit2\Models\Token;
/**
* Watch for user models being loaded or saved and handle installing an
* `authkit` object on them to allow the main application to easily interact
* with other services as the user or fetch data from the OIDC provider.
*/
class UserObserver
{
/*'retrieved', 'creating', 'created', 'updating', 'updated',
'saving', 'saved', 'restoring', 'restored', 'replicating',
'deleting', 'deleted', 'forceDeleted',*/
/**
* When a user model is saved we have to remove the authkit property from it
* to avoid Eloquent or another ORM from trying to save it. When we do so,
* we cache it here so we can restore it when the save is complete.
*
* @var array<mixed,string>
*/
protected static $token_cache = [];
public function retrieved($user)
/**
* Run in response to a user model being loaded, locating their token and
* creating a client to place on the model
*
* @param mixed $user
* @return void
*/
public function retrieved($user): void
{
// Find the token + refresh token for the user
$token = Token::where('user_id', $user->{$user->getAuthIdentifierName()})->first();
@ -22,25 +37,48 @@ class UserObserver
// Set a refresh callback on the token -- when it's been refreshed,
// save the new tokens.
$user->authkit->setRefreshCallback(function($oidc_token) use ($token) {
$token->access_token = $oidc_token->getAccessToken();
$token->refresh_token = $oidc_token->getRefreshToken();
$token->save();
});
$user->authkit->setRefreshCallback(
/**
* When a token has been refreshed, save the updated values
* to the token model
* @param \authkit2\Oidc\Token $oidc_token
* @return void
*/
function(\authkit2\Oidc\Token $oidc_token) use ($token) : void {
$token->access_token = $oidc_token->getAccessToken();
$token->refresh_token = $oidc_token->getRefreshToken();
$token->save();
});
}
public function saving($user)
/**
* Before we save a user model, remove the token/client so the ORM doesn't
* try and write those out.
*
* @param mixed $user
* @return void
*/
public function saving($user): void
{
if (isset($user->authkit))
static::$token_cache[$user->{$user->getAuthIdentifierName()}] = $user->authkit;
unset($user->authkit);
}
public function saved($user)
/**
* After a user model is saved, restore the client and token
*
* @param mixed $user
* @return void
*/
public function saved($user): void
{
$user_id = $user->{$user->getAuthIdentifierName()};
if (isset(static::$token_cache[$user_id]))
{
$user->authkit = static::$token_cache[$user_id];
unset(static::$token_cache[$user_id]);
}
}
}

19
src/Oidc/Authentication/Authentication.php

@ -10,10 +10,10 @@ abstract class Authentication
/**
* Authenticate the passed in HTTP request
*
* @param \GuzzleHttp\Psr7\Request $request request to authenticate
* @return \GuzzleHttp\Psr7\Request authenticated request
* @param \Psr\Http\Message\RequestInterface $request request to authenticate
* @return \Psr\Http\Message\RequestInterface authenticated request
*/
public abstract function authenticate(\GuzzleHttp\Psr7\Request $request): \GuzzleHttp\Psr7\Request;
public abstract function authenticate(\Psr\Http\Message\RequestInterface $request): \Psr\Http\Message\RequestInterface;
/**
* Wrap this provider up as a middleware appropriate for use directly with
@ -24,7 +24,12 @@ abstract class Authentication
public function getMiddleware(): callable
{
$auth = $this;
return function(callable $handler) use ($auth) {
return function(callable $handler) use ($auth) : callable {
/**
* @param \Psr\Http\Message\RequestInterface $request
* @param mixed[] $options
* @return mixed
*/
return function(\Psr\Http\Message\RequestInterface $request, array $options) use ($handler, $auth) {
return $handler(
$auth->authenticate($request),
@ -34,6 +39,12 @@ abstract class Authentication
};
}
/**
* Fetch a guzzle client with the authentication middleware included
*
* @param mixed[] $options options to pass through to the guzzle client
* @return \GuzzleHttp\Client
*/
public function getClient(array $options = []): \GuzzleHttp\Client
{
$stack = new \GuzzleHttp\HandlerStack();

6
src/Oidc/Authentication/ClientAuthentication.php

@ -37,10 +37,10 @@ class ClientAuthentication extends Authentication
* Client authentication uses HTTP basic authentication with the client id
* as the username and the client secret as the password.
*
* @param \GuzzleHttp\Psr7\Request $request request to authenticate
* @return \GuzzleHttp\Psr7\Request authenticated request
* @param \Psr\Http\Message\RequestInterface $request request to authenticate
* @return \Psr\Http\Message\RequestInterface authenticated request
*/
public function authenticate(\GuzzleHttp\Psr7\Request $request): \GuzzleHttp\Psr7\Request
public function authenticate(\Psr\Http\Message\RequestInterface $request): \Psr\Http\Message\RequestInterface
{
return $request->withHeader('Authorization', 'Basic '.base64_encode($this->client_id.':'.$this->client_secret));
}

15
src/Oidc/Authentication/TokenAuthentication.php

@ -17,7 +17,7 @@ class TokenAuthentication extends Authentication
/**
* Who to call if the token is expired
* @var callable
* @var ?callable
*/
protected $refresh_callback;
@ -25,6 +25,7 @@ class TokenAuthentication extends Authentication
* Create a new token authentication provider
*
* @param Token $token token to authenticate requests with
* @param ?callable $refreshCallback callback to generate us a new token when our existing one expires
*/
public function __construct(Token $token, callable $refreshCallback = null)
{
@ -32,6 +33,12 @@ class TokenAuthentication extends Authentication
$this->refresh_callback = $refreshCallback;
}
/**
* Set the callback to be called when the underlying token expires
*
* @param callable $refreshCallback
* @return void
*/
public function setRefreshCallback(callable $refreshCallback): void
{
$this->refresh_callback = $refreshCallback;
@ -42,10 +49,10 @@ class TokenAuthentication extends Authentication
*
* Token authentication uses the token as a bearer token.
*
* @param \GuzzleHttp\Psr7\Request $request request to authenticate
* @return \GuzzleHttp\Psr7\Request authenticated request
* @param \Psr\Http\Message\RequestInterface $request request to authenticate
* @return \Psr\Http\Message\RequestInterface authenticated request
*/
public function authenticate(\GuzzleHttp\Psr7\Request $request): \GuzzleHttp\Psr7\Request
public function authenticate(\Psr\Http\Message\RequestInterface $request): \Psr\Http\Message\RequestInterface
{
if ($this->token->isExpired() && isset($this->refresh_callback))
{

66
src/Oidc/Client.php

@ -35,7 +35,7 @@ class Client
/**
* OIDC config fetched from the server or restored from cache
* @var array<string,mixed>
* @var ?array<string,mixed>
*/
protected $oidc_config;
@ -76,7 +76,7 @@ class Client
*
* @return ?string
*/
public function getUrl(): string
public function getUrl(): ?string
{
return $this->oidc_url;
}
@ -84,17 +84,22 @@ class Client
/**
* Get the OpenId Connect configuration
*
* @return array
* @return array<string,string|array|bool>
*/
public function getConfiguration(): array
{
if (!isset($this->oidc_config))
{
$url = $this->oidc_url;
$this->oidc_config = Authkit2::cache('oidc.config.'.md5($this->oidc_url), function() use ($url) {
$response = (new \GuzzleHttp\Client())->get($url.'/.well-known/openid-configuration');
return json_decode($response->getBody(), true);
});
$this->oidc_config = Authkit2::cache('oidc.config.'.md5($this->oidc_url),
/**
* @return array<string,string|array|bool>
*/
function() use ($url) {
$response = (new \GuzzleHttp\Client())->get($url.'/.well-known/openid-configuration');
return json_decode($response->getBody(), true);
}
);
}
return $this->oidc_config;
@ -110,10 +115,15 @@ class Client
if (!isset($this->oidc_jwks))
{
$client = $this;
$this->oidc_jwks = Authkit2::cache('oidc.config.'.md5($this->oidc_url).'.jwks', function() use ($client) {
$response = $client->get($client->getConfiguration()['jwks_uri']);
return json_decode(json_encode($response), true);
});
$this->oidc_jwks = Authkit2::cache('oidc.config.'.md5($this->oidc_url).'.jwks',
/**
* @return array<string,array>
*/
function() use ($client) {
$response = $client->get($client->getConfiguration()['jwks_uri']);
return json_decode(json_encode($response), true);
}
);
}
return $this->oidc_jwks;
}
@ -219,6 +229,15 @@ class Client
return Token::fromResponse($this, $response);
}
/**
* Generate the URL to redirect to in order to initiate the three-legged
* oauth flow
*
* @param string $redirect_uri url to redirect the user to after authentication
* @param string[] $scopes scopes to request from the openid provider
* @param string $state nonce
* @return string fully formed url
*/
public function createAuthorizationRedirectUrl(string $redirect_uri, array $scopes, string $state): string
{
return $this->getEndpointUrl('authorization').'?'.http_build_query([
@ -230,6 +249,13 @@ class Client
]);
}
/**
* Generate the URL to redirect to in order to initiate a signout from the
* OIDC provider
*
* @param string $redirect_uri url to redirect the user to after logout
* @return string fully formed url
*/
public function createLogoutUrl(string $redirect_uri): string
{
return $this->getEndpointUrl('end_session').'?'.http_build_query([
@ -237,11 +263,26 @@ class Client
]);
}
/**
* Refresh a token using a refresh token
*
* @param Token $token expired token that includes a refresh token
* @return Token newly generated token
*/
public function refreshToken(Token $token): Token
{
return $this->createTokenFromRefreshToken($token->getRefreshToken());
$refresh_token = $token->getRefreshToken();
if (!isset($refresh_token))
throw new \Exception("Cannot refresh token initialized without refresh token");
return $this->createTokenFromRefreshToken($refresh_token);
}
/**
* Fetch the available information on the user from the OIDC provider
*
* @param Token $token token representing the user
* @return array<string,mixed>
*/
public function getTokenUserInfo(Token $token): array
{
return json_decode($token->getClient()->get($this->getEndpointUrl('userinfo'))->getBody(), true);
@ -249,5 +290,4 @@ class Client
// todo: introspect, etc
}

1
src/Oidc/Flows/ServiceAccountFlow.php

@ -2,7 +2,6 @@
namespace authkit2\Oidc\Flows;
use authkit2\Oidc\Client;
use authkit2\Oidc\Authentication\ClientAuthentication;
use authkit2\Oidc\Token;
/**

3
src/Oidc/Flows/UserFlow.php

@ -3,7 +3,6 @@
namespace authkit2\Oidc\Flows;
use authkit2\Authkit2;
use authkit2\Oidc\Client;
use authkit2\Oidc\Authentication\ClientAuthentication;
use authkit2\Oidc\Token;
/**
@ -74,8 +73,8 @@ class UserFlow
*
* THIS DOES NOT VALIDATE THE STATE. Call validateState first.
*
* @param string $redirect_uri url the oidc endpoint redirects back to; must match one given in call to getRedirectUrl
* @param string $code code returned by the authorization flow
* @param string $redirect_uri url the oidc endpoint redirects back to; must match one given in call to getRedirectUrl
* @return Token
*/
public function exchangeCodeForToken(string $code, string $redirect_uri): Token

46
src/Oidc/Token.php

@ -1,7 +1,6 @@
<?php
namespace authkit2\Oidc;
use authkit2\Authkit2;
use authkit2\Oidc\Client;
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
@ -25,7 +24,7 @@ class Token
/**
* OIDC JWT refresh token
* @var string
* @var ?string
*/
protected $refresh_token;
@ -81,7 +80,7 @@ class Token
/**
* Get a HTTP client that's authenticated with this token's credentials
*
* @param array $options
* @param array<string,mixed> $options
* @return \GuzzleHttp\Client
*/
public function getClient(array $options = []): \GuzzleHttp\Client
@ -90,26 +89,29 @@ class Token
// to ask it to refresh itself
$state = new \stdClass();
$state->refresher = function($token) use ($state) {
$client = $this->client;
$refresh_callback = $this->refresh_callback;
$state->refresher =
function(Token $token) use ($state) : Token {
$client = $this->client;
$refresh_callback = $this->refresh_callback;
// Refresh the token
$new_token = $client->createTokenFromRefreshToken($this->refresh_token);
// Refresh the token
if (!isset($this->refresh_token))
throw new \Exception("Token expired");
$new_token = $client->createTokenFromRefreshToken($this->refresh_token);
// Rebind this callback to the new token
$state->refresher->bindTo($new_token);
// Rebind this callback to the new token
$state->refresher->bindTo($new_token);
// Call the refresh callback
if (isset($refresh_callback))
{
// Copy over the token-level refresh callback
$new_token->setRefreshCallback($refresh_callback);
$refresh_callback($new_token);
}
// Call the refresh callback
if (isset($refresh_callback))
{
// Copy over the token-level refresh callback
$new_token->setRefreshCallback($refresh_callback);
$refresh_callback($new_token);
}
return $new_token;
};
return $new_token;
};
$auth = new Authentication\TokenAuthentication($this, $state->refresher);
return $auth->getClient($options);
@ -171,7 +173,7 @@ class Token
}
$this->refresh_token_data = json_decode(json_encode($this->decode($this->refresh_token)), true);
}
return $this->token_data;
return $this->refresh_token_data;
}
/**
@ -266,9 +268,9 @@ class Token
/**
* Fetch the user's refresh token
*
* @return string
* @return ?string
*/
public function getRefreshToken(): string
public function getRefreshToken(): ?string
{
return $this->refresh_token;
}

3
src/Providers/Authkit2ServiceProvider.php

@ -4,6 +4,9 @@ namespace authkit2\Providers;
use Illuminate\Support\ServiceProvider;
/**
* Core Authkit2 provider
*/
class Authkit2ServiceProvider extends ServiceProvider
{

9
src/Providers/AuthnServiceProvider.php

@ -19,10 +19,10 @@ class AuthnServiceProvider extends ServiceProvider
*/
public function register(): void
{
$this->app->singleton(\authkit2\Oidc\Flows\ServiceAccountFlow::class, function($app) {
$this->app->singleton(\authkit2\Oidc\Flows\ServiceAccountFlow::class, function() : \authkit2\Oidc\Flows\ServiceAccountFlow {
return new \authkit2\Oidc\Flows\ServiceAccountFlow(Authkit2::get_client());
});
$this->app->singleton(\authkit2\Oidc\Flows\UserFlow::class, function($app) {
$this->app->singleton(\authkit2\Oidc\Flows\UserFlow::class, function() : \authkit2\Oidc\Flows\UserFlow {
return new \authkit2\Oidc\Flows\UserFlow(Authkit2::get_client());
});
}
@ -36,7 +36,7 @@ class AuthnServiceProvider extends ServiceProvider
{
// register our observer on the user model so we can dynamically add/remove
// the token object + client
$user_model = config('auth.providers.users.model');
$user_model = (string)config('auth.providers.users.model');
$user_model::observe(\authkit2\Observers\UserObserver::class);
// Register all authentication routes
@ -66,6 +66,7 @@ class AuthnServiceProvider extends ServiceProvider
// TODO: For some reason route($name) isn't working here. We're
// just looking through the routes manually for now...
// @phan-suppress-next-line PhanTypeNoPropertiesForeach
foreach (\Route::getRoutes() as $route)
{
if ($route->getName() === 'login.callback')
@ -124,7 +125,7 @@ class AuthnServiceProvider extends ServiceProvider
// running a composer require/composer install without credentials present.
if (config('authkit.authn.openid.client_id') != null && config('authkit.authn.openid.client_secret') != null && config('authkit.authn.openid.endpoint') != null)
{
$this->app->booted(function($app) {
$this->app->booted(function() {
Authkit2::configure(config('authkit.authn.openid.client_id'), config('authkit.authn.openid.client_secret'), config('authkit.authn.openid.endpoint'));
});
}

10
src/Providers/AuthzServiceProvider.php

@ -12,10 +12,20 @@ use Illuminate\Support\ServiceProvider;
*/
class AuthzServiceProvider extends ServiceProvider
{
/**
* Register the additional service providers the authorization process depends on
*
* @return void
*/
public function register()
{
}
/**
* Initialize and register all authorization resources
*
* @return void
*/
public function boot()
{
}

Loading…
Cancel
Save