From 0c33c4cf4382ce54310c0de0072fd9256d24fbe2 Mon Sep 17 00:00:00 2001 From: Hafez Divandari Date: Mon, 30 Sep 2024 17:58:30 +0330 Subject: [PATCH] [13.x] Cleanup, improve types and tests (#1788) * cleanup and fix types * improve tests * formatting * formatting * formatting * formatting --- database/factories/ClientFactory.php | 33 +- ...1_000001_create_oauth_auth_codes_table.php | 4 +- ...00002_create_oauth_access_tokens_table.php | 4 +- ...0003_create_oauth_refresh_tokens_table.php | 4 +- ...6_01_000004_create_oauth_clients_table.php | 4 +- src/AccessToken.php | 4 +- src/ApiTokenCookieFactory.php | 39 +- src/AuthCode.php | 15 +- src/Bridge/AccessToken.php | 1 + src/Bridge/AccessTokenRepository.php | 24 +- src/Bridge/AuthCodeRepository.php | 10 +- src/Bridge/Client.php | 11 +- src/Bridge/ClientRepository.php | 18 +- src/Bridge/FormatsScopesForStorage.php | 6 +- src/Bridge/RefreshTokenRepository.php | 25 +- src/Bridge/Scope.php | 2 + src/Bridge/ScopeRepository.php | 11 +- src/Bridge/User.php | 2 + src/Bridge/UserRepository.php | 41 +-- src/Client.php | 75 ++-- src/ClientRepository.php | 20 +- src/Console/HashCommand.php | 11 +- src/Console/InstallCommand.php | 14 +- src/Console/KeysCommand.php | 35 +- src/Console/PurgeCommand.php | 8 +- src/Events/AccessTokenCreated.php | 36 +- src/Events/AccessTokenRevoked.php | 5 +- src/Events/RefreshTokenCreated.php | 26 +- src/Exceptions/InvalidAuthTokenException.php | 4 +- src/Exceptions/MissingScopeException.php | 14 +- src/Exceptions/OAuthServerException.php | 4 - src/Guards/TokenGuard.php | 190 ++++------ src/HasApiTokens.php | 51 +-- .../Controllers/AccessTokenController.php | 28 +- .../ApproveAuthorizationController.php | 30 +- .../Controllers/AuthorizationController.php | 119 ++----- src/Http/Controllers/ConvertsPsrResponses.php | 6 +- .../DenyAuthorizationController.php | 30 +- src/Http/Controllers/HandlesOAuthErrors.php | 9 +- .../Controllers/TransientTokenController.php | 21 +- .../Middleware/CheckClientCredentials.php | 25 +- .../CheckClientCredentialsForAnyScope.php | 25 +- src/Http/Middleware/CheckCredentials.php | 69 +--- src/Http/Middleware/CheckForAnyScope.php | 15 +- src/Http/Middleware/CheckScopes.php | 15 +- src/Http/Middleware/CreateFreshApiToken.php | 55 +-- src/Http/Responses/SimpleViewResponse.php | 7 +- src/Passport.php | 337 ++++++------------ src/PassportServiceProvider.php | 115 ++---- src/PassportUserProvider.php | 42 +-- src/PersonalAccessTokenFactory.php | 67 +--- src/PersonalAccessTokenResult.php | 33 +- src/RefreshToken.php | 19 +- src/Scope.php | 33 +- src/Token.php | 30 +- tests/Feature/ActingAsTest.php | 6 + .../BridgeAccessTokenRepositoryTest.php | 51 ++- .../BridgeRefreshTokenRepositoryTest.php | 30 +- tests/Feature/PassportServiceProviderTest.php | 56 +++ tests/Feature/PersonalAccessGrantTest.php | 7 + tests/Feature/RevokedTest.php | 6 +- tests/Unit/AuthorizationControllerTest.php | 52 +-- .../CheckClientCredentialsForAnyScopeTest.php | 9 +- tests/Unit/CheckClientCredentialsTest.php | 9 +- tests/Unit/CheckForAnyScopeTest.php | 20 +- tests/Unit/CheckScopesTest.php | 20 +- tests/Unit/PassportServiceProviderTest.php | 77 ---- tests/Unit/PassportTest.php | 2 +- tests/Unit/TokenGuardTest.php | 7 +- 69 files changed, 763 insertions(+), 1470 deletions(-) rename tests/{Unit => Feature}/BridgeAccessTokenRepositoryTest.php (54%) rename tests/{Unit => Feature}/BridgeRefreshTokenRepositoryTest.php (56%) create mode 100644 tests/Feature/PassportServiceProviderTest.php delete mode 100644 tests/Unit/PassportServiceProviderTest.php diff --git a/database/factories/ClientFactory.php b/database/factories/ClientFactory.php index 6791b911e..6a6c3e3ca 100644 --- a/database/factories/ClientFactory.php +++ b/database/factories/ClientFactory.php @@ -14,9 +14,9 @@ class ClientFactory extends Factory /** * Get the name of the model that is generated by the factory. * - * @return class-string<\Illuminate\Database\Eloquent\Model> + * @return class-string<\Laravel\Passport\Client> */ - public function modelName() + public function modelName(): string { return $this->model ?? Passport::clientModel(); } @@ -24,9 +24,9 @@ public function modelName() /** * Define the model's default state. * - * @return array + * @return array */ - public function definition() + public function definition(): array { return [ 'user_id' => null, @@ -40,37 +40,44 @@ public function definition() /** * Use as a Password client. - * - * @return $this */ - public function asPasswordClient() + public function asPasswordClient(): static { return $this->state([ 'grant_types' => ['password', 'refresh_token'], + 'redirect_uris' => [], ]); } /** * Use as a Personal Access Token client. - * - * @return $this */ - public function asPersonalAccessTokenClient() + public function asPersonalAccessTokenClient(): static { return $this->state([ 'grant_types' => ['personal_access'], + 'redirect_uris' => [], + ]); + } + + /** + * Use as an Implicit client. + */ + public function asImplicitClient(): static + { + return $this->state([ + 'grant_types' => ['implicit'], ]); } /** * Use as a Client Credentials client. - * - * @return $this */ - public function asClientCredentials() + public function asClientCredentials(): static { return $this->state([ 'grant_types' => ['client_credentials'], + 'redirect_uris' => [], ]); } } diff --git a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php index 81055f975..c700b50e8 100644 --- a/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +++ b/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php @@ -31,10 +31,8 @@ public function down(): void /** * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function getConnection(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php index 9dee781a3..3e50f7f76 100644 --- a/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php @@ -33,10 +33,8 @@ public function down(): void /** * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function getConnection(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php index c94c91abd..afb3c55c9 100644 --- a/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php @@ -29,10 +29,8 @@ public function down(): void /** * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function getConnection(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php index 21ec74624..7068d9239 100644 --- a/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2016_06_01_000004_create_oauth_clients_table.php @@ -34,10 +34,8 @@ public function down(): void /** * Get the migration connection name. - * - * @return string|null */ - public function getConnection() + public function getConnection(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/src/AccessToken.php b/src/AccessToken.php index 328baf80c..0fdff78c7 100644 --- a/src/AccessToken.php +++ b/src/AccessToken.php @@ -38,7 +38,7 @@ class AccessToken implements Arrayable, Jsonable, JsonSerializable /** * Create a new access token instance. * - * @param array $attributes + * @param array $attributes */ public function __construct(array $attributes = []) { @@ -84,7 +84,7 @@ public function transient(): bool */ public function revoke(): bool { - return Passport::token()->newQuery()->whereKey($this->oauth_access_token_id)->update(['revoked' => true]); + return (bool) Passport::token()->newQuery()->whereKey($this->oauth_access_token_id)->update(['revoked' => true]); } /** diff --git a/src/ApiTokenCookieFactory.php b/src/ApiTokenCookieFactory.php index a99dfd9bf..dfee08068 100644 --- a/src/ApiTokenCookieFactory.php +++ b/src/ApiTokenCookieFactory.php @@ -10,41 +10,19 @@ class ApiTokenCookieFactory { - /** - * The configuration repository implementation. - * - * @var \Illuminate\Contracts\Config\Repository - */ - protected $config; - - /** - * The encrypter implementation. - * - * @var \Illuminate\Contracts\Encryption\Encrypter - */ - protected $encrypter; - /** * Create an API token cookie factory instance. - * - * @param \Illuminate\Contracts\Config\Repository $config - * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter - * @return void */ - public function __construct(Config $config, Encrypter $encrypter) - { - $this->config = $config; - $this->encrypter = $encrypter; + public function __construct( + protected Config $config, + protected Encrypter $encrypter + ) { } /** * Create a new API token cookie. - * - * @param mixed $userId - * @param string $csrfToken - * @return \Symfony\Component\HttpFoundation\Cookie */ - public function make($userId, $csrfToken) + public function make(string|int $userId, string $csrfToken): Cookie { $config = $this->config->get('session'); @@ -65,13 +43,8 @@ public function make($userId, $csrfToken) /** * Create a new JWT token for the given user ID and CSRF token. - * - * @param mixed $userId - * @param string $csrfToken - * @param \Carbon\Carbon $expiration - * @return string */ - protected function createToken($userId, $csrfToken, Carbon $expiration) + protected function createToken(string|int $userId, string $csrfToken, Carbon $expiration): string { return JWT::encode([ 'sub' => $userId, diff --git a/src/AuthCode.php b/src/AuthCode.php index 6c3ce8591..4733db98e 100644 --- a/src/AuthCode.php +++ b/src/AuthCode.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class AuthCode extends Model { @@ -23,14 +24,14 @@ class AuthCode extends Model /** * The guarded attributes on the model. * - * @var array + * @var array|bool */ - protected $guarded = []; + protected $guarded = false; /** * The attributes that should be cast to native types. * - * @var array + * @var array */ protected $casts = [ 'revoked' => 'bool', @@ -56,19 +57,17 @@ class AuthCode extends Model * * @deprecated Will be removed in a future Laravel version. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\Laravel\Passport\Client, $this> */ - public function client() + public function client(): BelongsTo { return $this->belongsTo(Passport::clientModel()); } /** * Get the current connection name for the model. - * - * @return string|null */ - public function getConnectionName() + public function getConnectionName(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/src/Bridge/AccessToken.php b/src/Bridge/AccessToken.php index 14e482cdf..02ec739cf 100644 --- a/src/Bridge/AccessToken.php +++ b/src/Bridge/AccessToken.php @@ -15,6 +15,7 @@ class AccessToken implements AccessTokenEntityInterface /** * Create a new token instance. * + * @param non-empty-string|null $userIdentifier * @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes */ public function __construct(string|null $userIdentifier, array $scopes, ClientEntityInterface $client) diff --git a/src/Bridge/AccessTokenRepository.php b/src/Bridge/AccessTokenRepository.php index f2c68425a..7eb243bca 100644 --- a/src/Bridge/AccessTokenRepository.php +++ b/src/Bridge/AccessTokenRepository.php @@ -7,7 +7,6 @@ use Laravel\Passport\Events\AccessTokenCreated; use Laravel\Passport\Events\AccessTokenRevoked; use Laravel\Passport\Passport; -use Laravel\Passport\TokenRepository; use League\OAuth2\Server\Entities\AccessTokenEntityInterface; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; @@ -16,23 +15,12 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface { use FormatsScopesForStorage; - /** - * The token repository instance. - */ - protected TokenRepository $tokenRepository; - - /** - * The event dispatcher instance. - */ - protected Dispatcher $events; - /** * Create a new repository instance. */ - public function __construct(TokenRepository $tokenRepository, Dispatcher $events) - { - $this->events = $events; - $this->tokenRepository = $tokenRepository; + public function __construct( + protected Dispatcher $events + ) { } /** @@ -51,7 +39,7 @@ public function getNewToken( */ public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void { - $this->tokenRepository->create([ + Passport::token()->newQuery()->create([ 'id' => $id = $accessTokenEntity->getIdentifier(), 'user_id' => $userId = $accessTokenEntity->getUserIdentifier(), 'client_id' => $clientId = $accessTokenEntity->getClient()->getIdentifier(), @@ -70,7 +58,7 @@ public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEnt */ public function revokeAccessToken(string $tokenId): void { - if ($this->tokenRepository->revokeAccessToken($tokenId)) { + if (Passport::token()->newQuery()->whereKey($tokenId)->update(['revoked' => true])) { $this->events->dispatch(new AccessTokenRevoked($tokenId)); } } @@ -80,6 +68,6 @@ public function revokeAccessToken(string $tokenId): void */ public function isAccessTokenRevoked(string $tokenId): bool { - return $this->tokenRepository->isAccessTokenRevoked($tokenId); + return Passport::token()->newQuery()->whereKey($tokenId)->where('revoked', false)->doesntExist(); } } diff --git a/src/Bridge/AuthCodeRepository.php b/src/Bridge/AuthCodeRepository.php index 8e7135b0a..036a6be1d 100644 --- a/src/Bridge/AuthCodeRepository.php +++ b/src/Bridge/AuthCodeRepository.php @@ -23,16 +23,14 @@ public function getNewAuthCode(): AuthCodeEntityInterface */ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): void { - $attributes = [ + Passport::authCode()->forceFill([ 'id' => $authCodeEntity->getIdentifier(), 'user_id' => $authCodeEntity->getUserIdentifier(), 'client_id' => $authCodeEntity->getClient()->getIdentifier(), 'scopes' => $this->formatScopesForStorage($authCodeEntity->getScopes()), 'revoked' => false, 'expires_at' => $authCodeEntity->getExpiryDateTime(), - ]; - - Passport::authCode()->forceFill($attributes)->save(); + ])->save(); } /** @@ -40,7 +38,7 @@ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): voi */ public function revokeAuthCode(string $codeId): void { - Passport::authCode()->where('id', $codeId)->update(['revoked' => true]); + Passport::authCode()->newQuery()->whereKey($codeId)->update(['revoked' => true]); } /** @@ -48,6 +46,6 @@ public function revokeAuthCode(string $codeId): void */ public function isAuthCodeRevoked(string $codeId): bool { - return Passport::authCode()->where('id', $codeId)->where('revoked', 0)->doesntExist(); + return Passport::authCode()->newQuery()->whereKey($codeId)->where('revoked', false)->doesntExist(); } } diff --git a/src/Bridge/Client.php b/src/Bridge/Client.php index df4255957..df9522d14 100644 --- a/src/Bridge/Client.php +++ b/src/Bridge/Client.php @@ -10,26 +10,23 @@ class Client implements ClientEntityInterface { use ClientTrait, EntityTrait; - /** - * The client's provider. - */ - public ?string $provider; - /** * Create a new client instance. + * + * @param non-empty-string $identifier + * @param string[] $redirectUri */ public function __construct( string $identifier, string $name, array $redirectUri, bool $isConfidential = false, - ?string $provider = null + public ?string $provider = null ) { $this->setIdentifier($identifier); $this->name = $name; $this->isConfidential = $isConfidential; $this->redirectUri = $redirectUri; - $this->provider = $provider; } } diff --git a/src/Bridge/ClientRepository.php b/src/Bridge/ClientRepository.php index fe114f5f3..351c85889 100644 --- a/src/Bridge/ClientRepository.php +++ b/src/Bridge/ClientRepository.php @@ -10,23 +10,13 @@ class ClientRepository implements ClientRepositoryInterface { - /** - * The client model repository. - */ - protected ClientModelRepository $clients; - - /** - * The hasher implementation. - */ - protected Hasher $hasher; - /** * Create a new repository instance. */ - public function __construct(ClientModelRepository $clients, Hasher $hasher) - { - $this->clients = $clients; - $this->hasher = $hasher; + public function __construct( + protected ClientModelRepository $clients, + protected Hasher $hasher + ) { } /** diff --git a/src/Bridge/FormatsScopesForStorage.php b/src/Bridge/FormatsScopesForStorage.php index 8474416b7..7abea9cc1 100644 --- a/src/Bridge/FormatsScopesForStorage.php +++ b/src/Bridge/FormatsScopesForStorage.php @@ -2,6 +2,8 @@ namespace Laravel\Passport\Bridge; +use League\OAuth2\Server\Entities\ScopeEntityInterface; + trait FormatsScopesForStorage { /** @@ -22,8 +24,6 @@ public function formatScopesForStorage(array $scopes): string */ public function scopesToArray(array $scopes): array { - return array_map(function ($scope) { - return $scope->getIdentifier(); - }, $scopes); + return array_map(fn (ScopeEntityInterface $scope): string => $scope->getIdentifier(), $scopes); } } diff --git a/src/Bridge/RefreshTokenRepository.php b/src/Bridge/RefreshTokenRepository.php index 3a35b57cb..c798fb508 100644 --- a/src/Bridge/RefreshTokenRepository.php +++ b/src/Bridge/RefreshTokenRepository.php @@ -4,29 +4,18 @@ use Illuminate\Contracts\Events\Dispatcher; use Laravel\Passport\Events\RefreshTokenCreated; -use Laravel\Passport\RefreshTokenRepository as PassportRefreshTokenRepository; +use Laravel\Passport\Passport; use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; class RefreshTokenRepository implements RefreshTokenRepositoryInterface { - /** - * The refresh token repository instance. - */ - protected PassportRefreshTokenRepository $refreshTokenRepository; - - /** - * The event dispatcher instance. - */ - protected Dispatcher $events; - /** * Create a new repository instance. */ - public function __construct(PassportRefreshTokenRepository $refreshTokenRepository, Dispatcher $events) - { - $this->events = $events; - $this->refreshTokenRepository = $refreshTokenRepository; + public function __construct( + protected Dispatcher $events + ) { } /** @@ -42,7 +31,7 @@ public function getNewRefreshToken(): ?RefreshTokenEntityInterface */ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void { - $this->refreshTokenRepository->create([ + Passport::refreshToken()->newQuery()->create([ 'id' => $id = $refreshTokenEntity->getIdentifier(), 'access_token_id' => $accessTokenId = $refreshTokenEntity->getAccessToken()->getIdentifier(), 'revoked' => false, @@ -57,7 +46,7 @@ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshToken */ public function revokeRefreshToken(string $tokenId): void { - $this->refreshTokenRepository->revokeRefreshToken($tokenId); + Passport::refreshToken()->newQuery()->whereKey($tokenId)->update(['revoked' => true]); } /** @@ -65,6 +54,6 @@ public function revokeRefreshToken(string $tokenId): void */ public function isRefreshTokenRevoked(string $tokenId): bool { - return $this->refreshTokenRepository->isRefreshTokenRevoked($tokenId); + return Passport::refreshToken()->newQuery()->whereKey($tokenId)->where('revoked', false)->doesntExist(); } } diff --git a/src/Bridge/Scope.php b/src/Bridge/Scope.php index 4d77d6f35..65bd5a56f 100644 --- a/src/Bridge/Scope.php +++ b/src/Bridge/Scope.php @@ -12,6 +12,8 @@ class Scope implements ScopeEntityInterface /** * Create a new scope instance. + * + * @param non-empty-string $name */ public function __construct(string $name) { diff --git a/src/Bridge/ScopeRepository.php b/src/Bridge/ScopeRepository.php index 0cf73f732..574c4193b 100644 --- a/src/Bridge/ScopeRepository.php +++ b/src/Bridge/ScopeRepository.php @@ -15,8 +15,9 @@ class ScopeRepository implements ScopeRepositoryInterface /** * Create a new scope repository. */ - public function __construct(protected ClientRepository $clients) - { + public function __construct( + protected ClientRepository $clients + ) { } /** @@ -40,13 +41,13 @@ public function finalizeScopes( return collect($scopes) ->unless(in_array($grantType, ['password', 'personal_access', 'client_credentials']), fn (Collection $scopes): Collection => $scopes->reject( - fn (Scope $scope): bool => $scope->getIdentifier() === '*' + fn (ScopeEntityInterface $scope): bool => $scope->getIdentifier() === '*' ) ) - ->filter(fn (Scope $scope): bool => Passport::hasScope($scope->getIdentifier())) + ->filter(fn (ScopeEntityInterface $scope): bool => Passport::hasScope($scope->getIdentifier())) ->when($this->clients->findActive($clientEntity->getIdentifier()), fn (Collection $scopes, Client $client): Collection => $scopes->filter( - fn (Scope $scope): bool => $client->hasScope($scope->getIdentifier()) + fn (ScopeEntityInterface $scope): bool => $client->hasScope($scope->getIdentifier()) ) ) ->values() diff --git a/src/Bridge/User.php b/src/Bridge/User.php index afddf833f..c4d5015ca 100644 --- a/src/Bridge/User.php +++ b/src/Bridge/User.php @@ -11,6 +11,8 @@ class User implements UserEntityInterface /** * Create a new user instance. + * + * @param non-empty-string $identifier */ public function __construct(string $identifier) { diff --git a/src/Bridge/UserRepository.php b/src/Bridge/UserRepository.php index 8be747a56..620b84c51 100644 --- a/src/Bridge/UserRepository.php +++ b/src/Bridge/UserRepository.php @@ -10,17 +10,12 @@ class UserRepository implements UserRepositoryInterface { - /** - * The hasher implementation. - */ - protected Hasher $hasher; - /** * Create a new repository instance. */ - public function __construct(Hasher $hasher) - { - $this->hasher = $hasher; + public function __construct( + protected Hasher $hasher + ) { } /** @@ -41,29 +36,25 @@ public function getUserEntityByUserCredentials( if (method_exists($model, 'findAndValidateForPassport')) { $user = (new $model)->findAndValidateForPassport($username, $password); - if (! $user) { - return null; - } - - return new User($user->getAuthIdentifier()); + return $user ? new User($user->getAuthIdentifier()) : null; } - if (method_exists($model, 'findForPassport')) { - $user = (new $model)->findForPassport($username); - } else { - $user = (new $model)->where('email', $username)->first(); - } + $user = method_exists($model, 'findForPassport') + ? (new $model)->findForPassport($username) + : (new $model)->where('email', $username)->first(); if (! $user) { return null; - } elseif (method_exists($user, 'validateForPassportPasswordGrant')) { - if (! $user->validateForPassportPasswordGrant($password)) { - return null; - } - } elseif (! $this->hasher->check($password, $user->getAuthPassword())) { - return null; } - return new User($user->getAuthIdentifier()); + if (method_exists($user, 'validateForPassportPasswordGrant')) { + return $user->validateForPassportPasswordGrant($password) + ? new User($user->getAuthIdentifier()) + : null; + } + + return $this->hasher->check($password, $user->getAuthPassword()) + ? new User($user->getAuthIdentifier()) + : null; } } diff --git a/src/Client.php b/src/Client.php index 9eea7aa5a..7bda223db 100644 --- a/src/Client.php +++ b/src/Client.php @@ -4,14 +4,18 @@ use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; use Laravel\Passport\Database\Factories\ClientFactory; class Client extends Model { + /** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Laravel\Passport\Database\Factories\ClientFactory> */ use HasFactory; use ResolvesInheritedScopes; @@ -25,14 +29,14 @@ class Client extends Model /** * The guarded attributes on the model. * - * @var array + * @var array|bool */ - protected $guarded = []; + protected $guarded = false; /** * The attributes excluded from the model's JSON form. * - * @var array + * @var array */ protected $hidden = [ 'secret', @@ -41,7 +45,7 @@ class Client extends Model /** * The attributes that should be cast to native types. * - * @var array + * @var array */ protected $casts = [ 'grant_types' => 'array', @@ -56,16 +60,13 @@ class Client extends Model * The temporary plain-text client secret. * * This is only available during the request that created the client. - * - * @var string|null */ - public $plainSecret; + public ?string $plainSecret = null; /** * Create a new Eloquent model instance. * - * @param array $attributes - * @return void + * @param array $attributes */ public function __construct(array $attributes = []) { @@ -77,14 +78,14 @@ public function __construct(array $attributes = []) /** * Get the user that the client belongs to. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\Illuminate\Foundation\Auth\User, $this> */ - public function user() + public function user(): BelongsTo { $provider = $this->provider ?: config('auth.guards.api.provider'); return $this->belongsTo( - config("auth.providers.{$provider}.model") + config("auth.providers.$provider.model") ); } @@ -93,9 +94,9 @@ public function user() * * @deprecated Will be removed in a future Laravel version. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\Laravel\Passport\AuthCode, $this> */ - public function authCodes() + public function authCodes(): HasMany { return $this->hasMany(Passport::authCodeModel(), 'client_id'); } @@ -103,9 +104,9 @@ public function authCodes() /** * Get all of the tokens that belong to the client. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\Laravel\Passport\Token, $this> */ - public function tokens() + public function tokens(): HasMany { return $this->hasMany(Passport::tokenModel(), 'client_id'); } @@ -114,21 +115,16 @@ public function tokens() * The temporary non-hashed client secret. * * This is only available once during the request that created the client. - * - * @return string|null */ - public function getPlainSecretAttribute() + public function getPlainSecretAttribute(): ?string { return $this->plainSecret; } /** * Set the value of the secret attribute. - * - * @param string|null $value - * @return void */ - public function setSecretAttribute($value) + public function setSecretAttribute(?string $value): void { $this->plainSecret = $value; @@ -171,11 +167,8 @@ public function skipsAuthorization(Authenticatable $user, array $scopes): bool /** * Determine if the client has the given grant type. - * - * @param string $grantType - * @return bool */ - public function hasGrantType($grantType) + public function hasGrantType(string $grantType): bool { if (isset($this->attributes['grant_types']) && is_array($this->grant_types)) { return in_array($grantType, $this->grant_types); @@ -200,10 +193,8 @@ public function hasScope(string $scope): bool /** * Determine if the client is a confidential client. - * - * @return bool */ - public function confidential() + public function confidential(): bool { return ! empty($this->secret); } @@ -211,49 +202,41 @@ public function confidential() /** * Get the columns that should receive a unique identifier. * - * @return array + * @return array */ - public function uniqueIds() + public function uniqueIds(): array { return $this->usesUniqueIds ? [$this->getKeyName()] : []; } /** * Generate a new key for the model. - * - * @return string */ - public function newUniqueId() + public function newUniqueId(): ?string { return $this->usesUniqueIds ? (string) Str::orderedUuid() : null; } /** * Get the auto-incrementing key type. - * - * @return string */ - public function getKeyType() + public function getKeyType(): string { return $this->usesUniqueIds ? 'string' : $this->keyType; } /** * Get the value indicating whether the IDs are incrementing. - * - * @return bool */ - public function getIncrementing() + public function getIncrementing(): bool { return $this->usesUniqueIds ? false : $this->incrementing; } /** * Get the current connection name for the model. - * - * @return string|null */ - public function getConnectionName() + public function getConnectionName(): ?string { return $this->connection ?? config('passport.connection'); } @@ -261,9 +244,9 @@ public function getConnectionName() /** * Create a new factory instance for the model. * - * @return \Illuminate\Database\Eloquent\Factories\Factory + * @return \Laravel\Passport\Database\Factories\ClientFactory */ - protected static function newFactory() + protected static function newFactory(): Factory { return ClientFactory::new(); } diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 3fb3b501a..0402fc7b8 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Contracts\Auth\Authenticatable; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Str; use RuntimeException; @@ -77,10 +78,11 @@ public function activeForUser($userId) public function personalAccessClient(string $provider): Client { return Passport::client() + ->newQuery() ->where('revoked', false) ->whereNull('user_id') - ->where(function ($query) use ($provider) { - $query->when($provider === config('auth.guards.api.provider'), function ($query) { + ->where(function (Builder $query) use ($provider) { + $query->when($provider === config('auth.guards.api.provider'), function (Builder $query) { $query->orWhereNull('provider'); })->orWhere('provider', $provider); }) @@ -95,8 +97,9 @@ public function personalAccessClient(string $provider): Client /** * Store a new client. * - * @param string[] $redirectUris * @param string[] $grantTypes + * @param string[] $redirectUris + * @param \Laravel\Passport\HasApiTokens $user */ protected function create( string $name, @@ -129,7 +132,7 @@ protected function create( return $user ? $user->clients()->forceCreate($attributes) - : $client->forceCreate($attributes); + : $client->newQuery()->forceCreate($attributes); } /** @@ -203,17 +206,12 @@ public function update(Client $client, string $name, array $redirectUris): bool /** * Regenerate the client secret. - * - * @param \Laravel\Passport\Client $client - * @return \Laravel\Passport\Client */ - public function regenerateSecret(Client $client) + public function regenerateSecret(Client $client): bool { - $client->forceFill([ + return $client->forceFill([ 'secret' => Str::random(40), ])->save(); - - return $client; } /** diff --git a/src/Console/HashCommand.php b/src/Console/HashCommand.php index 65cf62c32..92a18e806 100644 --- a/src/Console/HashCommand.php +++ b/src/Console/HashCommand.php @@ -26,15 +26,12 @@ class HashCommand extends Command /** * Execute the console command. - * - * @return void */ - public function handle() + public function handle(): void { - if ($this->option('force') || $this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) { - $model = Passport::clientModel(); - - foreach ((new $model)->whereNotNull('secret')->cursor() as $client) { + if ($this->option('force') || + $this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) { + foreach (Passport::client()->newQuery()->whereNotNull('secret')->cursor() as $client) { if (Hash::isHashed($client->secret) && ! Hash::needsRehash($client->secret)) { continue; } diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 8bc1ac14f..013201cf7 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -26,12 +26,13 @@ class InstallCommand extends Command /** * Execute the console command. - * - * @return void */ - public function handle() + public function handle(): void { - $this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]); + $this->call('passport:keys', [ + '--force' => $this->option('force'), + '--length' => $this->option('length'), + ]); $this->call('vendor:publish', ['--tag' => 'passport-config']); $this->call('vendor:publish', ['--tag' => 'passport-migrations']); @@ -40,7 +41,10 @@ public function handle() $this->call('migrate'); if ($this->confirm('Would you like to create the "personal access" grant client?', true)) { - $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); + $this->call('passport:client', [ + '--personal' => true, + '--name' => config('app.name'), + ]); } } } diff --git a/src/Console/KeysCommand.php b/src/Console/KeysCommand.php index f9d417876..6fbf83be8 100644 --- a/src/Console/KeysCommand.php +++ b/src/Console/KeysCommand.php @@ -3,9 +3,7 @@ namespace Laravel\Passport\Console; use Illuminate\Console\Command; -use Illuminate\Support\Arr; use Laravel\Passport\Passport; -use phpseclib\Crypt\RSA as LegacyRSA; use phpseclib3\Crypt\RSA; use Symfony\Component\Console\Attribute\AsCommand; @@ -30,10 +28,8 @@ class KeysCommand extends Command /** * Execute the console command. - * - * @return int */ - public function handle() + public function handle(): int { [$publicKey, $privateKey] = [ Passport::keyPath('oauth-public.key'), @@ -43,28 +39,21 @@ public function handle() if ((file_exists($publicKey) || file_exists($privateKey)) && ! $this->option('force')) { $this->components->error('Encryption keys already exist. Use the --force option to overwrite them.'); - return 1; - } else { - if (class_exists(LegacyRSA::class)) { - $keys = (new LegacyRSA)->createKey($this->input ? (int) $this->option('length') : 4096); - - file_put_contents($publicKey, Arr::get($keys, 'publickey')); - file_put_contents($privateKey, Arr::get($keys, 'privatekey')); - } else { - $key = RSA::createKey($this->input ? (int) $this->option('length') : 4096); + return Command::FAILURE; + } - file_put_contents($publicKey, (string) $key->getPublicKey()); - file_put_contents($privateKey, (string) $key); - } + $key = RSA::createKey((int) $this->option('length')); - if (! windows_os()) { - chmod($publicKey, 0660); - chmod($privateKey, 0600); - } + file_put_contents($publicKey, (string) $key->getPublicKey()); + file_put_contents($privateKey, (string) $key); - $this->components->info('Encryption keys generated successfully.'); + if (! windows_os()) { + chmod($publicKey, 0660); + chmod($privateKey, 0600); } - return 0; + $this->components->info('Encryption keys generated successfully.'); + + return Command::SUCCESS; } } diff --git a/src/Console/PurgeCommand.php b/src/Console/PurgeCommand.php index 7c43589cb..0012c5ba6 100644 --- a/src/Console/PurgeCommand.php +++ b/src/Console/PurgeCommand.php @@ -31,7 +31,7 @@ class PurgeCommand extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $revoked = $this->option('revoked') || ! $this->option('expired'); @@ -43,9 +43,9 @@ public function handle() ->when($revoked, fn () => $query->orWhere('revoked', true)) ->when($expired, fn () => $query->orWhere('expires_at', '<', $expired)); - Passport::token()->where($constraint)->delete(); - Passport::authCode()->where($constraint)->delete(); - Passport::refreshToken()->where($constraint)->delete(); + Passport::token()->newQuery()->where($constraint)->delete(); + Passport::authCode()->newQuery()->where($constraint)->delete(); + Passport::refreshToken()->newQuery()->where($constraint)->delete(); $this->components->info(sprintf('Purged %s.', implode(' and ', array_filter([ $revoked ? 'revoked items' : null, diff --git a/src/Events/AccessTokenCreated.php b/src/Events/AccessTokenCreated.php index f40bf9ce2..6e67db70f 100644 --- a/src/Events/AccessTokenCreated.php +++ b/src/Events/AccessTokenCreated.php @@ -4,39 +4,13 @@ class AccessTokenCreated { - /** - * The newly created token ID. - * - * @var string - */ - public $tokenId; - - /** - * The ID of the user associated with the token. - * - * @var string|null - */ - public $userId; - - /** - * The ID of the client associated with the token. - * - * @var string - */ - public $clientId; - /** * Create a new event instance. - * - * @param string $tokenId - * @param string|null $userId - * @param string $clientId - * @return void */ - public function __construct($tokenId, $userId, $clientId) - { - $this->userId = $userId; - $this->tokenId = $tokenId; - $this->clientId = $clientId; + public function __construct( + public string $tokenId, + public ?string $userId, + public string $clientId + ) { } } diff --git a/src/Events/AccessTokenRevoked.php b/src/Events/AccessTokenRevoked.php index 71a87976d..6fb0bc47a 100644 --- a/src/Events/AccessTokenRevoked.php +++ b/src/Events/AccessTokenRevoked.php @@ -6,12 +6,9 @@ class AccessTokenRevoked { /** * Create a new event instance. - * - * @param string $tokenId - * @return void */ public function __construct( - public string $tokenId, + public string $tokenId ) { } } diff --git a/src/Events/RefreshTokenCreated.php b/src/Events/RefreshTokenCreated.php index 08430f2b6..fb6da59d0 100644 --- a/src/Events/RefreshTokenCreated.php +++ b/src/Events/RefreshTokenCreated.php @@ -4,30 +4,12 @@ class RefreshTokenCreated { - /** - * The newly created refresh token ID. - * - * @var string - */ - public $refreshTokenId; - - /** - * The access token ID. - * - * @var string - */ - public $accessTokenId; - /** * Create a new event instance. - * - * @param string $refreshTokenId - * @param string $accessTokenId - * @return void */ - public function __construct($refreshTokenId, $accessTokenId) - { - $this->accessTokenId = $accessTokenId; - $this->refreshTokenId = $refreshTokenId; + public function __construct( + public string $refreshTokenId, + public string $accessTokenId + ) { } } diff --git a/src/Exceptions/InvalidAuthTokenException.php b/src/Exceptions/InvalidAuthTokenException.php index 6427929e4..6f93e7607 100644 --- a/src/Exceptions/InvalidAuthTokenException.php +++ b/src/Exceptions/InvalidAuthTokenException.php @@ -8,10 +8,8 @@ class InvalidAuthTokenException extends AuthorizationException { /** * Create a new InvalidAuthTokenException for different auth tokens. - * - * @return static */ - public static function different() + public static function different(): static { return new static('The provided auth token for the request is different from the session auth token.'); } diff --git a/src/Exceptions/MissingScopeException.php b/src/Exceptions/MissingScopeException.php index f4f0f4e11..8ed0b5130 100644 --- a/src/Exceptions/MissingScopeException.php +++ b/src/Exceptions/MissingScopeException.php @@ -10,18 +10,16 @@ class MissingScopeException extends AuthorizationException /** * The scopes that the user did not have. * - * @var array + * @var string[] */ - protected $scopes; + protected array $scopes; /** * Create a new missing scope exception. * - * @param array|string $scopes - * @param string $message - * @return void + * @param string[]|string $scopes */ - public function __construct($scopes = [], $message = 'Invalid scope(s) provided.') + public function __construct(array|string $scopes = [], string $message = 'Invalid scope(s) provided.') { parent::__construct($message); @@ -31,9 +29,9 @@ public function __construct($scopes = [], $message = 'Invalid scope(s) provided. /** * Get the scopes that the user did not have. * - * @return array + * @return string[] */ - public function scopes() + public function scopes(): array { return $this->scopes; } diff --git a/src/Exceptions/OAuthServerException.php b/src/Exceptions/OAuthServerException.php index dcdf5cd36..31d7cca9f 100644 --- a/src/Exceptions/OAuthServerException.php +++ b/src/Exceptions/OAuthServerException.php @@ -10,10 +10,6 @@ class OAuthServerException extends HttpResponseException { /** * Create a new OAuthServerException. - * - * @param \League\OAuth2\Server\Exception\OAuthServerException $e - * @param \Illuminate\Http\Response $response - * @return void */ public function __construct(LeagueException $e, Response $response) { diff --git a/src/Guards/TokenGuard.php b/src/Guards/TokenGuard.php index 8ffbb9316..0339fc658 100644 --- a/src/Guards/TokenGuard.php +++ b/src/Guards/TokenGuard.php @@ -6,9 +6,8 @@ use Firebase\JWT\JWT; use Firebase\JWT\Key; use Illuminate\Auth\GuardHelpers; -use Illuminate\Container\Container; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\Guard; -use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Cookie\CookieValuePrefix; use Illuminate\Cookie\Middleware\EncryptCookies; @@ -23,19 +22,13 @@ use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Nyholm\Psr7\Factory\Psr17Factory; +use Psr\Http\Message\ServerRequestInterface; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; class TokenGuard implements Guard { use GuardHelpers, Macroable; - /** - * The resource server instance. - * - * @var \League\OAuth2\Server\ResourceServer - */ - protected $server; - /** * The user provider implementation. * @@ -43,83 +36,50 @@ class TokenGuard implements Guard */ protected $provider; - /** - * The client repository instance. - * - * @var \Laravel\Passport\ClientRepository - */ - protected $clients; - - /** - * The encrypter implementation. - * - * @var \Illuminate\Contracts\Encryption\Encrypter - */ - protected $encrypter; - - /** - * The request instance. - * - * @var \Illuminate\Http\Request - */ - protected $request; - /** * The currently authenticated client. - * - * @var \Laravel\Passport\Client|null */ - protected $client; + protected ?Client $client = null; /** * Create a new token guard instance. - * - * @param \League\OAuth2\Server\ResourceServer $server - * @param \Laravel\Passport\PassportUserProvider $provider - * @param \Laravel\Passport\ClientRepository $clients - * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter - * @param \Illuminate\Http\Request $request - * @return void */ public function __construct( - ResourceServer $server, + protected ResourceServer $server, PassportUserProvider $provider, - ClientRepository $clients, - Encrypter $encrypter, - Request $request + protected ClientRepository $clients, + protected Encrypter $encrypter, + protected Request $request ) { - $this->server = $server; - $this->clients = $clients; $this->provider = $provider; - $this->encrypter = $encrypter; - $this->request = $request; } /** * Get the user for the incoming request. - * - * @return \Illuminate\Contracts\Auth\Authenticatable|null */ - public function user() + public function user(): ?Authenticatable { if (! is_null($this->user)) { return $this->user; } if ($this->request->bearerToken()) { - return $this->user = $this->authenticateViaBearerToken($this->request); - } elseif ($this->request->cookie(Passport::cookie())) { - return $this->user = $this->authenticateViaCookie($this->request); + return $this->user = $this->authenticateViaBearerToken(); + } + + if ($this->request->cookie(Passport::cookie())) { + return $this->user = $this->authenticateViaCookie(); } + + return null; } /** * Validate a user's credentials. * - * @param array $credentials - * @return bool + * @param array $credentials */ - public function validate(array $credentials = []) + public function validate(array $credentials = []): bool { return ! is_null((new static( $this->server, @@ -132,40 +92,37 @@ public function validate(array $credentials = []) /** * Get the client for the incoming request. - * - * @return \Laravel\Passport\Client|null */ - public function client() + public function client(): ?Client { if (! is_null($this->client)) { return $this->client; } if ($this->request->bearerToken()) { - if (! $psr = $this->getPsrRequestViaBearerToken($this->request)) { - return; + if (! $psr = $this->getPsrRequestViaBearerToken()) { + return null; } return $this->client = $this->clients->findActive( $psr->getAttribute('oauth_client_id') ); - } elseif ($this->request->cookie(Passport::cookie())) { - if ($token = $this->getTokenViaCookie($this->request)) { - return $this->client = $this->clients->findActive($token['aud']); - } } + + if ($this->request->cookie(Passport::cookie()) && $token = $this->getTokenViaCookie()) { + return $this->client = $this->clients->findActive($token['aud']); + } + + return null; } /** * Authenticate the incoming request via the Bearer token. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Contracts\Auth\Authenticatable|null */ - protected function authenticateViaBearerToken($request) + protected function authenticateViaBearerToken(): ?Authenticatable { - if (! $psr = $this->getPsrRequestViaBearerToken($request)) { - return; + if (! $psr = $this->getPsrRequestViaBearerToken()) { + return null; } $client = $this->clients->findActive( @@ -175,7 +132,7 @@ protected function authenticateViaBearerToken($request) if (! $client || ($client->provider && $client->provider !== $this->provider->getProviderName())) { - return; + return null; } $this->setClient($client); @@ -188,24 +145,19 @@ protected function authenticateViaBearerToken($request) ); if (! $user) { - return; + return null; } // Next, we will assign a token instance to this user which the developers may use // to determine if the token has a given scope, etc. This will be useful during // authorization such as within the developer's Laravel model policy classes. - $token = AccessToken::fromPsrRequest($psr); - - return $user->withAccessToken($token); + return $user->withAccessToken(AccessToken::fromPsrRequest($psr)); } /** * Authenticate and get the incoming PSR-7 request via the Bearer token. - * - * @param \Illuminate\Http\Request $request - * @return \Psr\Http\Message\ServerRequestInterface|null */ - protected function getPsrRequestViaBearerToken($request) + protected function getPsrRequestViaBearerToken(): ?ServerRequestInterface { // First, we will convert the Symfony request to a PSR-7 implementation which will // be compatible with the base OAuth2 library. The Symfony bridge can perform a @@ -215,29 +167,26 @@ protected function getPsrRequestViaBearerToken($request) new Psr17Factory, new Psr17Factory, new Psr17Factory - ))->createRequest($request); + ))->createRequest($this->request); try { return $this->server->validateAuthenticatedRequest($psr); } catch (OAuthServerException $e) { - $request->headers->set('Authorization', '', true); + $this->request->headers->set('Authorization', '', true); + + report($e); - Container::getInstance()->make( - ExceptionHandler::class - )->report($e); + return null; } } /** * Authenticate the incoming request via the token cookie. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Contracts\Auth\Authenticatable|null */ - protected function authenticateViaCookie($request) + protected function authenticateViaCookie(): ?Authenticatable { - if (! $token = $this->getTokenViaCookie($request)) { - return; + if (! $token = $this->getTokenViaCookie()) { + return null; } // If this user exists, we will return this user and attach a "transient" token to @@ -246,31 +195,32 @@ protected function authenticateViaCookie($request) if ($user = $this->provider->retrieveById($token['sub'])) { return $user->withAccessToken(new TransientToken); } + + return null; } /** * Get the token cookie via the incoming request. * - * @param \Illuminate\Http\Request $request - * @return array|null + * @return array|null */ - protected function getTokenViaCookie($request) + protected function getTokenViaCookie(): ?array { // If we need to retrieve the token from the cookie, it'll be encrypted so we must // first decrypt the cookie and then attempt to find the token value within the // database. If we can't decrypt the value we'll bail out with a null return. try { - $token = $this->decodeJwtTokenCookie($request); - } catch (Exception $e) { - return; + $token = $this->decodeJwtTokenCookie(); + } catch (Exception) { + return null; } // We will compare the CSRF token in the decoded API token against the CSRF header // sent with the request. If they don't match then this request isn't sent from // a valid source and we won't authenticate the request for further handling. - if (! Passport::$ignoreCsrfToken && (! $this->validCsrf($token, $request) || - time() >= $token['expiry'])) { - return; + if (! Passport::$ignoreCsrfToken && + (! $this->validCsrf($token) || time() >= $token['expiry'])) { + return null; } return $token; @@ -279,12 +229,11 @@ protected function getTokenViaCookie($request) /** * Decode and decrypt the JWT token cookie. * - * @param \Illuminate\Http\Request $request - * @return array + * @return array */ - protected function decodeJwtTokenCookie($request) + protected function decodeJwtTokenCookie(): array { - $jwt = $request->cookie(Passport::cookie()); + $jwt = $this->request->cookie(Passport::cookie()); return (array) JWT::decode( Passport::$decryptsCookies @@ -297,28 +246,23 @@ protected function decodeJwtTokenCookie($request) /** * Determine if the CSRF / header are valid and match. * - * @param array $token - * @param \Illuminate\Http\Request $request - * @return bool + * @param array $token */ - protected function validCsrf($token, $request) + protected function validCsrf(array $token): bool { return isset($token['csrf']) && hash_equals( - $token['csrf'], (string) $this->getTokenFromRequest($request) + $token['csrf'], $this->getTokenFromRequest() ); } /** * Get the CSRF token from the request. - * - * @param \Illuminate\Http\Request $request - * @return string */ - protected function getTokenFromRequest($request) + protected function getTokenFromRequest(): string { - $token = $request->header('X-CSRF-TOKEN'); + $token = $this->request->header('X-CSRF-TOKEN'); - if (! $token && $header = $request->header('X-XSRF-TOKEN')) { + if (! $token && $header = $this->request->header('X-XSRF-TOKEN')) { $token = CookieValuePrefix::remove($this->encrypter->decrypt($header, static::serialized())); } @@ -327,11 +271,8 @@ protected function getTokenFromRequest($request) /** * Set the current request instance. - * - * @param \Illuminate\Http\Request $request - * @return $this */ - public function setRequest(Request $request) + public function setRequest(Request $request): static { $this->request = $request; @@ -340,21 +281,16 @@ public function setRequest(Request $request) /** * Determine if the cookie contents should be serialized. - * - * @return bool */ - public static function serialized() + public static function serialized(): bool { return EncryptCookies::serialized('XSRF-TOKEN'); } /** * Set the client for the current request. - * - * @param \Laravel\Passport\Client $client - * @return $this */ - public function setClient(Client $client) + public function setClient(Client $client): static { $this->client = $client; diff --git a/src/HasApiTokens.php b/src/HasApiTokens.php index 8d09a4598..b57212967 100644 --- a/src/HasApiTokens.php +++ b/src/HasApiTokens.php @@ -2,24 +2,23 @@ namespace Laravel\Passport; -use Illuminate\Container\Container; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\HasMany; use LogicException; trait HasApiTokens { /** * The current access token for the authentication user. - * - * @var \Laravel\Passport\AccessToken|\Laravel\Passport\TransientToken|null */ - protected $accessToken; + protected AccessToken|TransientToken|null $accessToken; /** * Get all of the user's registered OAuth clients. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\Laravel\Passport\Client, $this> */ - public function clients() + public function clients(): HasMany { return $this->hasMany(Passport::clientModel(), 'user_id'); } @@ -27,17 +26,17 @@ public function clients() /** * Get all of the access tokens for the user. * - * @return \Illuminate\Database\Eloquent\Relations\HasMany + * @return \Illuminate\Database\Eloquent\Relations\HasMany<\Laravel\Passport\Token, $this> */ - public function tokens() + public function tokens(): HasMany { return $this->hasMany(Passport::tokenModel(), 'user_id') - ->where(function ($query) { - $query->whereHas('client', function ($query) { - $query->where(function ($query) { + ->where(function (Builder $query) { + $query->whereHas('client', function (Builder $query) { + $query->where(function (Builder $query) { $provider = $this->getProvider(); - $query->when($provider === config('auth.guards.api.provider'), function ($query) { + $query->when($provider === config('auth.guards.api.provider'), function (Builder $query) { $query->orWhereNull('provider'); })->orWhere('provider', $provider); }); @@ -47,51 +46,42 @@ public function tokens() /** * Get the current access token being used by the user. - * - * @return \Laravel\Passport\AccessToken|\Laravel\Passport\TransientToken|null */ - public function token() + public function token(): AccessToken|TransientToken|null { return $this->accessToken; } /** * Get the access token currently associated with the user. - * - * @return \Laravel\Passport\AccessToken|\Laravel\Passport\TransientToken|null */ - public function currentAccessToken() + public function currentAccessToken(): AccessToken|TransientToken|null { return $this->token(); } /** * Determine if the current API token has a given scope. - * - * @param string $scope - * @return bool */ - public function tokenCan($scope) + public function tokenCan(string $scope): bool { return $this->accessToken && $this->accessToken->can($scope); } /** * Create a new personal access token for the user. - * - * @param string $name - * @param array $scopes - * @return \Laravel\Passport\PersonalAccessTokenResult */ - public function createToken($name, array $scopes = []) + public function createToken(string $name, array $scopes = []): PersonalAccessTokenResult { - return Container::getInstance()->make(PersonalAccessTokenFactory::class)->make( + return app(PersonalAccessTokenFactory::class)->make( $this->getAuthIdentifier(), $name, $scopes, $this->getProvider() ); } /** * Get the user provider name. + * + * @throws \LogicException */ public function getProvider(): string { @@ -108,11 +98,8 @@ public function getProvider(): string /** * Set the current access token for the user. - * - * @param \Laravel\Passport\AccessToken|\Laravel\Passport\TransientToken|null $accessToken - * @return $this */ - public function withAccessToken($accessToken) + public function withAccessToken(AccessToken|TransientToken|null $accessToken): static { $this->accessToken = $accessToken; diff --git a/src/Http/Controllers/AccessTokenController.php b/src/Http/Controllers/AccessTokenController.php index 7da5aa22c..eae2779bc 100644 --- a/src/Http/Controllers/AccessTokenController.php +++ b/src/Http/Controllers/AccessTokenController.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Http\Controllers; +use Illuminate\Http\Response; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\Exception\OAuthServerException; use Nyholm\Psr7\Response as Psr7Response; @@ -11,35 +12,22 @@ class AccessTokenController { use ConvertsPsrResponses, HandlesOAuthErrors; - /** - * The authorization server. - * - * @var \League\OAuth2\Server\AuthorizationServer - */ - protected $server; - /** * Create a new controller instance. - * - * @param \League\OAuth2\Server\AuthorizationServer $server - * @return void */ - public function __construct(AuthorizationServer $server) - { - $this->server = $server; + public function __construct( + protected AuthorizationServer $server + ) { } /** - * Authorize a client to access the user's account. - * - * @param \Psr\Http\Message\ServerRequestInterface $request - * @return \Illuminate\Http\Response + * Issue an access token. */ - public function issueToken(ServerRequestInterface $request) + public function issueToken(ServerRequestInterface $request): Response { return $this->withErrorHandling(function () use ($request) { - if (array_key_exists('grant_type', $attributes = (array) $request->getParsedBody()) - && $attributes['grant_type'] === 'personal_access') { + if (array_key_exists('grant_type', $attributes = (array) $request->getParsedBody()) && + $attributes['grant_type'] === 'personal_access') { throw OAuthServerException::unsupportedGrantType(); } diff --git a/src/Http/Controllers/ApproveAuthorizationController.php b/src/Http/Controllers/ApproveAuthorizationController.php index b675ea031..385f7fbc3 100644 --- a/src/Http/Controllers/ApproveAuthorizationController.php +++ b/src/Http/Controllers/ApproveAuthorizationController.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Http\Controllers; use Illuminate\Http\Request; +use Illuminate\Http\Response; use League\OAuth2\Server\AuthorizationServer; use Nyholm\Psr7\Response as Psr7Response; @@ -10,40 +11,25 @@ class ApproveAuthorizationController { use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession; - /** - * The authorization server. - * - * @var \League\OAuth2\Server\AuthorizationServer - */ - protected $server; - /** * Create a new controller instance. - * - * @param \League\OAuth2\Server\AuthorizationServer $server - * @return void */ - public function __construct(AuthorizationServer $server) - { - $this->server = $server; + public function __construct( + protected AuthorizationServer $server + ) { } /** * Approve the authorization request. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response */ - public function approve(Request $request) + public function approve(Request $request): Response { $authRequest = $this->getAuthRequestFromSession($request); $authRequest->setAuthorizationApproved(true); - return $this->withErrorHandling(function () use ($authRequest) { - return $this->convertResponse( - $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) - ); - }); + return $this->withErrorHandling(fn () => $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + )); } } diff --git a/src/Http/Controllers/AuthorizationController.php b/src/Http/Controllers/AuthorizationController.php index 4cd76dd0e..396b5966e 100644 --- a/src/Http/Controllers/AuthorizationController.php +++ b/src/Http/Controllers/AuthorizationController.php @@ -2,17 +2,22 @@ namespace Laravel\Passport\Http\Controllers; +use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Illuminate\Support\Facades\Date; use Illuminate\Support\Str; use Laravel\Passport\Bridge\User; +use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; use Laravel\Passport\Contracts\AuthorizationViewResponse; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Passport; use League\OAuth2\Server\AuthorizationServer; +use League\OAuth2\Server\Entities\ScopeEntityInterface; use League\OAuth2\Server\Exception\OAuthServerException; +use League\OAuth2\Server\RequestTypes\AuthorizationRequestInterface; use Nyholm\Psr7\Response as Psr7Response; use Psr\Http\Message\ServerRequestInterface; @@ -20,62 +25,30 @@ class AuthorizationController { use ConvertsPsrResponses, HandlesOAuthErrors; - /** - * The authorization server. - * - * @var \League\OAuth2\Server\AuthorizationServer - */ - protected $server; - - /** - * The guard implementation. - * - * @var \Illuminate\Contracts\Auth\StatefulGuard - */ - protected $guard; - - /** - * The authorization view response implementation. - * - * @var \Laravel\Passport\Contracts\AuthorizationViewResponse - */ - protected $response; - /** * Create a new controller instance. - * - * @param \League\OAuth2\Server\AuthorizationServer $server - * @param \Illuminate\Contracts\Auth\StatefulGuard $guard - * @param \Laravel\Passport\Contracts\AuthorizationViewResponse $response - * @return void */ - public function __construct(AuthorizationServer $server, - StatefulGuard $guard, - AuthorizationViewResponse $response) - { - $this->server = $server; - $this->guard = $guard; - $this->response = $response; + public function __construct( + protected AuthorizationServer $server, + protected StatefulGuard $guard, + protected AuthorizationViewResponse $response, + protected ClientRepository $clients + ) { } /** * Authorize a client to access the user's account. - * - * @param \Psr\Http\Message\ServerRequestInterface $psrRequest - * @param \Illuminate\Http\Request $request - * @param \Laravel\Passport\ClientRepository $clients - * @return \Illuminate\Http\Response|\Laravel\Passport\Contracts\AuthorizationViewResponse */ - public function authorize(ServerRequestInterface $psrRequest, Request $request, ClientRepository $clients) + public function authorize(ServerRequestInterface $psrRequest, Request $request): Response|AuthorizationViewResponse { - $authRequest = $this->withErrorHandling(function () use ($psrRequest) { - return $this->server->validateAuthorizationRequest($psrRequest); - }); + $authRequest = $this->withErrorHandling(fn () => $this->server->validateAuthorizationRequest($psrRequest)); if ($this->guard->guest()) { - return $request->get('prompt') === 'none' - ? $this->denyRequest($authRequest) - : $this->promptForLogin($request); + if ($request->get('prompt') === 'none') { + return $this->denyRequest($authRequest); + } + + $this->promptForLogin($request); } if ($request->get('prompt') === 'login' && @@ -84,14 +57,14 @@ public function authorize(ServerRequestInterface $psrRequest, Request $request, $request->session()->invalidate(); $request->session()->regenerateToken(); - return $this->promptForLogin($request); + $this->promptForLogin($request); } $request->session()->forget('promptedForLogin'); $scopes = $this->parseScopes($authRequest); $user = $this->guard->user(); - $client = $clients->find($authRequest->getClient()->getIdentifier()); + $client = $this->clients->find($authRequest->getClient()->getIdentifier()); if ($request->get('prompt') !== 'consent' && ($client->skipsAuthorization($user, $scopes) || $this->hasGrantedScopes($user, $client, $scopes))) { @@ -115,29 +88,25 @@ public function authorize(ServerRequestInterface $psrRequest, Request $request, } /** - * Transform the authorization requests's scopes into Scope instances. + * Transform the authorization request's scopes into Scope instances. * - * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @return array + * @return \Laravel\Passport\Scope[] */ - protected function parseScopes($authRequest) + protected function parseScopes(AuthorizationRequestInterface $authRequest): array { return Passport::scopesFor( - collect($authRequest->getScopes())->map(function ($scope) { - return $scope->getIdentifier(); - })->unique()->all() + collect($authRequest->getScopes())->map( + fn (ScopeEntityInterface $scope): string => $scope->getIdentifier() + )->unique()->all() ); } /** * Determine if the given user has already granted the client access to the scopes. * - * @param \Illuminate\Contracts\Auth\Authenticatable $user - * @param \Laravel\Passport\Client $client - * @param array $scopes - * @return bool + * @param \Laravel\Passport\Scope[] $scopes */ - protected function hasGrantedScopes($user, $client, $scopes) + protected function hasGrantedScopes(Authenticatable $user, Client $client, array $scopes): bool { $tokensScopes = $client->tokens()->where([ ['user_id', '=', $user->getAuthIdentifier()], @@ -151,32 +120,22 @@ protected function hasGrantedScopes($user, $client, $scopes) /** * Approve the authorization request. - * - * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @param \Illuminate\Contracts\Auth\Authenticatable $user - * @return \Illuminate\Http\Response */ - protected function approveRequest($authRequest, $user) + protected function approveRequest(AuthorizationRequestInterface $authRequest, Authenticatable $user): Response { $authRequest->setUser(new User($user->getAuthIdentifier())); $authRequest->setAuthorizationApproved(true); - return $this->withErrorHandling(function () use ($authRequest) { - return $this->convertResponse( - $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) - ); - }); + return $this->withErrorHandling(fn () => $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + )); } /** * Deny the authorization request. - * - * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest - * @param \Illuminate\Contracts\Auth\Authenticatable|null $user - * @return \Illuminate\Http\Response */ - protected function denyRequest($authRequest, $user = null) + protected function denyRequest(AuthorizationRequestInterface $authRequest, ?Authenticatable $user = null): Response { if (is_null($user)) { $uri = $authRequest->getRedirectUri() @@ -197,21 +156,17 @@ protected function denyRequest($authRequest, $user = null) $authRequest->setAuthorizationApproved(false); - return $this->withErrorHandling(function () use ($authRequest) { - return $this->convertResponse( - $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) - ); - }); + return $this->withErrorHandling(fn () => $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + )); } /** * Prompt the user to login by throwing an AuthenticationException. * - * @param \Illuminate\Http\Request $request - * * @throws \Laravel\Passport\Exceptions\AuthenticationException */ - protected function promptForLogin($request) + protected function promptForLogin(Request $request): never { $request->session()->put('promptedForLogin', true); diff --git a/src/Http/Controllers/ConvertsPsrResponses.php b/src/Http/Controllers/ConvertsPsrResponses.php index 07146504a..81ccc7e5a 100644 --- a/src/Http/Controllers/ConvertsPsrResponses.php +++ b/src/Http/Controllers/ConvertsPsrResponses.php @@ -3,16 +3,14 @@ namespace Laravel\Passport\Http\Controllers; use Illuminate\Http\Response; +use Psr\Http\Message\ResponseInterface; trait ConvertsPsrResponses { /** * Convert a PSR7 response to a Illuminate Response. - * - * @param \Psr\Http\Message\ResponseInterface $psrResponse - * @return \Illuminate\Http\Response */ - public function convertResponse($psrResponse) + public function convertResponse(ResponseInterface $psrResponse): Response { return new Response( $psrResponse->getBody(), diff --git a/src/Http/Controllers/DenyAuthorizationController.php b/src/Http/Controllers/DenyAuthorizationController.php index 4c287667b..0c2b0154d 100644 --- a/src/Http/Controllers/DenyAuthorizationController.php +++ b/src/Http/Controllers/DenyAuthorizationController.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Http\Controllers; use Illuminate\Http\Request; +use Illuminate\Http\Response; use League\OAuth2\Server\AuthorizationServer; use Nyholm\Psr7\Response as Psr7Response; @@ -10,40 +11,25 @@ class DenyAuthorizationController { use ConvertsPsrResponses, HandlesOAuthErrors, RetrievesAuthRequestFromSession; - /** - * The authorization server. - * - * @var \League\OAuth2\Server\AuthorizationServer - */ - protected $server; - /** * Create a new controller instance. - * - * @param \League\OAuth2\Server\AuthorizationServer $server - * @return void */ - public function __construct(AuthorizationServer $server) - { - $this->server = $server; + public function __construct( + protected AuthorizationServer $server + ) { } /** * Deny the authorization request. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\RedirectResponse */ - public function deny(Request $request) + public function deny(Request $request): Response { $authRequest = $this->getAuthRequestFromSession($request); $authRequest->setAuthorizationApproved(false); - return $this->withErrorHandling(function () use ($authRequest) { - return $this->convertResponse( - $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) - ); - }); + return $this->withErrorHandling(fn () => $this->convertResponse( + $this->server->completeAuthorizationRequest($authRequest, new Psr7Response) + )); } } diff --git a/src/Http/Controllers/HandlesOAuthErrors.php b/src/Http/Controllers/HandlesOAuthErrors.php index b036f96bc..8c1ba18dc 100644 --- a/src/Http/Controllers/HandlesOAuthErrors.php +++ b/src/Http/Controllers/HandlesOAuthErrors.php @@ -2,6 +2,7 @@ namespace Laravel\Passport\Http\Controllers; +use Closure; use Laravel\Passport\Exceptions\OAuthServerException; use League\OAuth2\Server\Exception\OAuthServerException as LeagueException; use Nyholm\Psr7\Response as Psr7Response; @@ -13,12 +14,14 @@ trait HandlesOAuthErrors /** * Perform the given callback with exception handling. * - * @param \Closure $callback - * @return mixed + * @template TResult + * + * @param \Closure(): TResult $callback + * @return TResult * * @throws \Laravel\Passport\Exceptions\OAuthServerException */ - protected function withErrorHandling($callback) + protected function withErrorHandling(Closure $callback) { try { return $callback(); diff --git a/src/Http/Controllers/TransientTokenController.php b/src/Http/Controllers/TransientTokenController.php index 2cb56ba3e..2abc77421 100644 --- a/src/Http/Controllers/TransientTokenController.php +++ b/src/Http/Controllers/TransientTokenController.php @@ -8,31 +8,18 @@ class TransientTokenController { - /** - * The cookie factory instance. - * - * @var \Laravel\Passport\ApiTokenCookieFactory - */ - protected $cookieFactory; - /** * Create a new controller instance. - * - * @param \Laravel\Passport\ApiTokenCookieFactory $cookieFactory - * @return void */ - public function __construct(ApiTokenCookieFactory $cookieFactory) - { - $this->cookieFactory = $cookieFactory; + public function __construct( + protected ApiTokenCookieFactory $cookieFactory + ) { } /** * Get a fresh transient token cookie for the authenticated user. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response */ - public function refresh(Request $request) + public function refresh(Request $request): Response { return (new Response('Refreshed.'))->withCookie($this->cookieFactory->make( $request->user()->getAuthIdentifier(), $request->session()->token() diff --git a/src/Http/Middleware/CheckClientCredentials.php b/src/Http/Middleware/CheckClientCredentials.php index 49180afa8..b29ab3f25 100644 --- a/src/Http/Middleware/CheckClientCredentials.php +++ b/src/Http/Middleware/CheckClientCredentials.php @@ -2,36 +2,19 @@ namespace Laravel\Passport\Http\Middleware; -use Laravel\Passport\Exceptions\AuthenticationException; +use Laravel\Passport\AccessToken; use Laravel\Passport\Exceptions\MissingScopeException; class CheckClientCredentials extends CheckCredentials { /** - * Validate token credentials. + * Validate token scopes. * - * @param \Laravel\Passport\AccessToken $token - * @return void - * - * @throws \Laravel\Passport\Exceptions\AuthenticationException - */ - protected function validateCredentials($token) - { - if (! $token) { - throw new AuthenticationException; - } - } - - /** - * Validate token credentials. - * - * @param \Laravel\Passport\AccessToken $token - * @param array $scopes - * @return void + * @param string[] $scopes * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ - protected function validateScopes($token, $scopes) + protected function validateScopes(AccessToken $token, array $scopes): void { if (in_array('*', $token->oauth_scopes)) { return; diff --git a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php index cb9467b00..9a3766b9f 100644 --- a/src/Http/Middleware/CheckClientCredentialsForAnyScope.php +++ b/src/Http/Middleware/CheckClientCredentialsForAnyScope.php @@ -2,36 +2,19 @@ namespace Laravel\Passport\Http\Middleware; -use Laravel\Passport\Exceptions\AuthenticationException; +use Laravel\Passport\AccessToken; use Laravel\Passport\Exceptions\MissingScopeException; class CheckClientCredentialsForAnyScope extends CheckCredentials { /** - * Validate token credentials. + * Validate token scopes. * - * @param \Laravel\Passport\AccessToken $token - * @return void - * - * @throws \Laravel\Passport\Exceptions\AuthenticationException - */ - protected function validateCredentials($token) - { - if (! $token) { - throw new AuthenticationException; - } - } - - /** - * Validate token credentials. - * - * @param \Laravel\Passport\AccessToken $token - * @param array $scopes - * @return void + * @param string[] $scopes * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ - protected function validateScopes($token, $scopes) + protected function validateScopes(AccessToken $token, array $scopes): void { if (in_array('*', $token->oauth_scopes)) { return; diff --git a/src/Http/Middleware/CheckCredentials.php b/src/Http/Middleware/CheckCredentials.php index 64bf6082c..3cb12c372 100644 --- a/src/Http/Middleware/CheckCredentials.php +++ b/src/Http/Middleware/CheckCredentials.php @@ -3,40 +3,31 @@ namespace Laravel\Passport\Http\Middleware; use Closure; +use Illuminate\Http\Request; use Laravel\Passport\AccessToken; use Laravel\Passport\Exceptions\AuthenticationException; use League\OAuth2\Server\Exception\OAuthServerException; use League\OAuth2\Server\ResourceServer; use Nyholm\Psr7\Factory\Psr17Factory; use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; +use Symfony\Component\HttpFoundation\Response; abstract class CheckCredentials { - /** - * The Resource Server instance. - * - * @var \League\OAuth2\Server\ResourceServer - */ - protected $server; - /** * Create a new middleware instance. - * - * @param \League\OAuth2\Server\ResourceServer $server - * @return void */ - public function __construct(ResourceServer $server) - { - $this->server = $server; + public function __construct( + protected ResourceServer $server + ) { } /** * Specify the scopes for the middleware. * - * @param array|string $scopes - * @return string + * @param string[]|string ...$scopes */ - public static function using(...$scopes) + public static function using(...$scopes): string { if (is_array($scopes[0])) { return static::class.':'.implode(',', $scopes[0]); @@ -48,14 +39,12 @@ public static function using(...$scopes) /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param mixed ...$scopes - * @return mixed + * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next + * @param string[]|string ...$scopes * * @throws \Laravel\Passport\Exceptions\AuthenticationException */ - public function handle($request, Closure $next, ...$scopes) + public function handle(Request $request, Closure $next, string ...$scopes): Response { $psr = (new PsrHttpFactory( new Psr17Factory, @@ -66,51 +55,21 @@ public function handle($request, Closure $next, ...$scopes) try { $psr = $this->server->validateAuthenticatedRequest($psr); - } catch (OAuthServerException $e) { + } catch (OAuthServerException) { throw new AuthenticationException; } - $this->validate($psr, $scopes); + $this->validateScopes(AccessToken::fromPsrRequest($psr), $scopes); return $next($request); } - /** - * Validate the scopes and token on the incoming request. - * - * @param \Psr\Http\Message\ServerRequestInterface $psr - * @param array $scopes - * @return void - * - * @throws \Laravel\Passport\Exceptions\MissingScopeException|\Illuminate\Auth\AuthenticationException - */ - protected function validate($psr, $scopes) - { - $token = AccessToken::fromPsrRequest($psr); - - $this->validateCredentials($token); - - $this->validateScopes($token, $scopes); - } - - /** - * Validate token credentials. - * - * @param \Laravel\Passport\AccessToken $token - * @return void - * - * @throws \Laravel\Passport\Exceptions\AuthenticationException - */ - abstract protected function validateCredentials($token); - /** * Validate token scopes. * - * @param \Laravel\Passport\AccessToken $token - * @param array $scopes - * @return void + * @param string[] $scopes * * @throws \Laravel\Passport\Exceptions\MissingScopeException */ - abstract protected function validateScopes($token, $scopes); + abstract protected function validateScopes(AccessToken $token, array $scopes): void; } diff --git a/src/Http/Middleware/CheckForAnyScope.php b/src/Http/Middleware/CheckForAnyScope.php index 77d9bb1a3..b7882a78b 100644 --- a/src/Http/Middleware/CheckForAnyScope.php +++ b/src/Http/Middleware/CheckForAnyScope.php @@ -2,18 +2,20 @@ namespace Laravel\Passport\Http\Middleware; +use Closure; +use Illuminate\Http\Request; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; +use Symfony\Component\HttpFoundation\Response; class CheckForAnyScope { /** * Specify the scopes for the middleware. * - * @param array|string $scopes - * @return string + * @param string[]|string ...$scopes */ - public static function using(...$scopes) + public static function using(...$scopes): string { if (is_array($scopes[0])) { return static::class.':'.implode(',', $scopes[0]); @@ -25,14 +27,11 @@ public static function using(...$scopes) /** * Handle the incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param mixed ...$scopes - * @return \Illuminate\Http\Response + * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next * * @throws \Laravel\Passport\Exceptions\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException */ - public function handle($request, $next, ...$scopes) + public function handle(Request $request, Closure $next, string ...$scopes): Response { if (! $request->user() || ! $request->user()->token()) { throw new AuthenticationException; diff --git a/src/Http/Middleware/CheckScopes.php b/src/Http/Middleware/CheckScopes.php index fdcead33a..4d00eb96e 100644 --- a/src/Http/Middleware/CheckScopes.php +++ b/src/Http/Middleware/CheckScopes.php @@ -2,18 +2,20 @@ namespace Laravel\Passport\Http\Middleware; +use Closure; +use Illuminate\Http\Request; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Exceptions\MissingScopeException; +use Symfony\Component\HttpFoundation\Response; class CheckScopes { /** * Specify the scopes for the middleware. * - * @param array|string $scopes - * @return string + * @param string[]|string ...$scopes */ - public static function using(...$scopes) + public static function using(...$scopes): string { if (is_array($scopes[0])) { return static::class.':'.implode(',', $scopes[0]); @@ -25,14 +27,11 @@ public static function using(...$scopes) /** * Handle the incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param mixed ...$scopes - * @return \Illuminate\Http\Response + * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next * * @throws \Laravel\Passport\Exceptions\AuthenticationException|\Laravel\Passport\Exceptions\MissingScopeException */ - public function handle($request, $next, ...$scopes) + public function handle(Request $request, Closure $next, string ...$scopes): Response { if (! $request->user() || ! $request->user()->token()) { throw new AuthenticationException; diff --git a/src/Http/Middleware/CreateFreshApiToken.php b/src/Http/Middleware/CreateFreshApiToken.php index 1429362c8..90d1e3204 100644 --- a/src/Http/Middleware/CreateFreshApiToken.php +++ b/src/Http/Middleware/CreateFreshApiToken.php @@ -4,44 +4,31 @@ use Closure; use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; use Illuminate\Http\Response; use Laravel\Passport\ApiTokenCookieFactory; use Laravel\Passport\Passport; +use Symfony\Component\HttpFoundation\Response as BaseResponse; class CreateFreshApiToken { - /** - * The API token cookie factory instance. - * - * @var \Laravel\Passport\ApiTokenCookieFactory - */ - protected $cookieFactory; - /** * The authentication guard. - * - * @var string */ - protected $guard; + protected ?string $guard = null; /** * Create a new middleware instance. - * - * @param \Laravel\Passport\ApiTokenCookieFactory $cookieFactory - * @return void */ - public function __construct(ApiTokenCookieFactory $cookieFactory) - { - $this->cookieFactory = $cookieFactory; + public function __construct( + protected ApiTokenCookieFactory $cookieFactory + ) { } /** * Specify the guard for the middleware. - * - * @param string|null $guard - * @return string */ - public static function using($guard = null) + public static function using(?string $guard = null): string { $guard = is_null($guard) ? '' : ':'.$guard; @@ -51,12 +38,9 @@ public static function using($guard = null) /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null $guard - * @return mixed + * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ - public function handle($request, Closure $next, $guard = null) + public function handle(Request $request, Closure $next, ?string $guard = null): BaseResponse { $this->guard = $guard; @@ -73,12 +57,8 @@ public function handle($request, Closure $next, $guard = null) /** * Determine if the given request should receive a fresh token. - * - * @param \Illuminate\Http\Request $request - * @param \Illuminate\Http\Response $response - * @return bool */ - protected function shouldReceiveFreshToken($request, $response) + protected function shouldReceiveFreshToken(Request $request, BaseResponse $response): bool { return $this->requestShouldReceiveFreshToken($request) && $this->responseShouldReceiveFreshToken($response); @@ -86,22 +66,16 @@ protected function shouldReceiveFreshToken($request, $response) /** * Determine if the request should receive a fresh token. - * - * @param \Illuminate\Http\Request $request - * @return bool */ - protected function requestShouldReceiveFreshToken($request) + protected function requestShouldReceiveFreshToken(Request $request): bool { return $request->isMethod('GET') && $request->user($this->guard); } /** * Determine if the response should receive a fresh token. - * - * @param \Illuminate\Http\Response $response - * @return bool */ - protected function responseShouldReceiveFreshToken($response) + protected function responseShouldReceiveFreshToken(BaseResponse $response): bool { return ($response instanceof Response || $response instanceof JsonResponse) && @@ -112,11 +86,8 @@ protected function responseShouldReceiveFreshToken($response) * Determine if the given response already contains an API token. * * This avoids us overwriting a just "refreshed" token. - * - * @param \Illuminate\Http\Response $response - * @return bool */ - protected function alreadyContainsToken($response) + protected function alreadyContainsToken(BaseResponse $response): bool { foreach ($response->headers->getCookies() as $cookie) { if ($cookie->getName() === Passport::cookie()) { diff --git a/src/Http/Responses/SimpleViewResponse.php b/src/Http/Responses/SimpleViewResponse.php index 7d1335d19..a71727f34 100644 --- a/src/Http/Responses/SimpleViewResponse.php +++ b/src/Http/Responses/SimpleViewResponse.php @@ -17,9 +17,12 @@ class SimpleViewResponse implements AuthorizationViewResponse /** * Create a new response instance. + * + * @param (\Closure(array): (\Symfony\Component\HttpFoundation\Response))|string $view */ - public function __construct(protected Closure|string $view) - { + public function __construct( + protected Closure|string $view + ) { } /** diff --git a/src/Passport.php b/src/Passport.php index 561c62da7..503e650f2 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -7,9 +7,11 @@ use DateInterval; use DateTimeInterface; use Illuminate\Contracts\Encryption\Encrypter; +use Illuminate\Support\Collection; use Laravel\Passport\Contracts\AuthorizationViewResponse; use Laravel\Passport\Http\Responses\SimpleViewResponse; use League\OAuth2\Server\ResourceServer; +use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; use Mockery; use Psr\Http\Message\ServerRequestInterface; @@ -17,189 +19,149 @@ class Passport { /** * Indicates if Passport should validate the permissions of its encryption keys. - * - * @var bool */ - public static $validateKeyPermissions = false; + public static bool $validateKeyPermissions = false; /** * Indicates if the implicit grant type is enabled. - * - * @var bool|null */ - public static $implicitGrantEnabled = false; + public static bool $implicitGrantEnabled = false; /** * Indicates if the password grant type is enabled. - * - * @var bool|null */ - public static $passwordGrantEnabled = false; + public static bool $passwordGrantEnabled = false; /** * The default scope. - * - * @var string */ - public static $defaultScope = ''; + public static string $defaultScope = ''; /** * All of the scopes defined for the application. * - * @var array + * @var array */ - public static $scopes = [ + public static array $scopes = [ // ]; /** * The interval when access tokens expire. - * - * @var \DateInterval|null */ - public static $tokensExpireIn; + public static ?DateInterval $tokensExpireIn; /** * The date when refresh tokens expire. - * - * @var \DateInterval|null */ - public static $refreshTokensExpireIn; + public static ?DateInterval $refreshTokensExpireIn; /** * The date when personal access tokens expire. - * - * @var \DateInterval|null */ - public static $personalAccessTokensExpireIn; + public static ?DateInterval $personalAccessTokensExpireIn; /** * The name for API token cookies. - * - * @var string */ - public static $cookie = 'laravel_token'; + public static string $cookie = 'laravel_token'; /** * Indicates if Passport should ignore incoming CSRF tokens. - * - * @var bool */ - public static $ignoreCsrfToken = false; + public static bool $ignoreCsrfToken = false; /** * The storage location of the encryption keys. - * - * @var string */ - public static $keyPath; + public static string $keyPath; /** * The access token entity class name. * - * @var string + * @var class-string<\Laravel\Passport\Bridge\AccessToken> */ - public static $accessTokenEntity = 'Laravel\Passport\Bridge\AccessToken'; + public static string $accessTokenEntity = Bridge\AccessToken::class; /** * The auth code model class name. * - * @var string + * @var class-string<\Laravel\Passport\AuthCode> */ - public static $authCodeModel = 'Laravel\Passport\AuthCode'; + public static string $authCodeModel = AuthCode::class; /** * The client model class name. * - * @var string + * @var class-string<\Laravel\Passport\Client> */ - public static $clientModel = 'Laravel\Passport\Client'; + public static string $clientModel = Client::class; /** - * Indicates if client's are identified by UUIDs. - * - * @var bool + * Indicates if clients are identified by UUIDs. */ - public static $clientUuids = true; + public static bool $clientUuids = true; /** * The token model class name. * - * @var string + * @var class-string<\Laravel\Passport\Token> */ - public static $tokenModel = 'Laravel\Passport\Token'; + public static string $tokenModel = Token::class; /** * The refresh token model class name. * - * @var string + * @var class-string<\Laravel\Passport\RefreshToken> */ - public static $refreshTokenModel = 'Laravel\Passport\RefreshToken'; + public static string $refreshTokenModel = RefreshToken::class; /** * Indicates if Passport should unserializes cookies. - * - * @var bool */ - public static $unserializesCookies = false; + public static bool $unserializesCookies = false; /** * Indicates if Passport should decrypt cookies. - * - * @var bool */ - public static $decryptsCookies = true; + public static bool $decryptsCookies = true; /** * The callback that should be used to generate JWT encryption keys. * - * @var callable + * @var (\Closure(\Illuminate\Contracts\Encryption\Encrypter): string)|null */ - public static $tokenEncryptionKeyCallback; + public static ?Closure $tokenEncryptionKeyCallback = null; /** * Indicates the scope should inherit its parent scope. - * - * @var bool */ - public static $withInheritedScopes = false; + public static bool $withInheritedScopes = false; /** * The authorization server response type. - * - * @var \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface|null */ - public static $authorizationServerResponseType; + public static ?ResponseTypeInterface $authorizationServerResponseType = null; /** * Indicates if Passport routes will be registered. - * - * @var bool */ - public static $registersRoutes = true; + public static bool $registersRoutes = true; /** * Enable the implicit grant type. - * - * @return static */ - public static function enableImplicitGrant() + public static function enableImplicitGrant(): void { static::$implicitGrantEnabled = true; - - return new static; } /** * Enable the password grant type. - * - * @return static */ - public static function enablePasswordGrant() + public static function enablePasswordGrant(): void { static::$passwordGrantEnabled = true; - - return new static; } /** @@ -207,10 +169,9 @@ public static function enablePasswordGrant() * * @deprecated Use defaultScopes. * - * @param array|string $scope - * @return void + * @param string[]|string $scope */ - public static function setDefaultScope($scope) + public static function setDefaultScope(array|string $scope): void { static::$defaultScope = is_array($scope) ? implode(' ', $scope) : $scope; } @@ -244,20 +205,17 @@ public static function validScopes(array $scopes): array /** * Get all of the defined scope IDs. * - * @return array + * @return string[] */ - public static function scopeIds() + public static function scopeIds(): array { return static::scopes()->pluck('id')->values()->all(); } /** * Determine if the given scope has been defined. - * - * @param string $id - * @return bool */ - public static function hasScope($id) + public static function hasScope(string $id): bool { return $id === '*' || array_key_exists($id, static::$scopes); } @@ -265,140 +223,113 @@ public static function hasScope($id) /** * Get all of the scopes defined for the application. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ - public static function scopes() + public static function scopes(): Collection { - return collect(static::$scopes)->map(function ($description, $id) { - return new Scope($id, $description); - })->values(); + return collect(static::$scopes)->map( + fn (string $description, string $id): Scope => new Scope($id, $description) + )->values(); } /** * Get all of the scopes matching the given IDs. * - * @param array $ids - * @return array + * @param string[] $ids + * @return \Laravel\Passport\Scope[] */ - public static function scopesFor(array $ids) + public static function scopesFor(array $ids): array { - return collect($ids)->map(function ($id) { - if (isset(static::$scopes[$id])) { - return new Scope($id, static::$scopes[$id]); - } - })->filter()->values()->all(); + return collect($ids)->map( + fn (string $id): ?Scope => isset(static::$scopes[$id]) ? new Scope($id, static::$scopes[$id]) : null + )->filter()->values()->all(); } /** * Define the scopes for the application. * - * @param array $scopes - * @return void + * @param array $scopes */ - public static function tokensCan(array $scopes) + public static function tokensCan(array $scopes): void { static::$scopes = $scopes; } /** * Get or set when access tokens expire. - * - * @param \DateTimeInterface|\DateInterval|null $date - * @return \DateInterval|static */ - public static function tokensExpireIn(DateTimeInterface|DateInterval $date = null) + public static function tokensExpireIn(DateTimeInterface|DateInterval|null $date = null): DateInterval { if (is_null($date)) { - return static::$tokensExpireIn ?? new DateInterval('P1Y'); + return static::$tokensExpireIn ??= new DateInterval('P1Y'); } - static::$tokensExpireIn = $date instanceof DateTimeInterface + return static::$tokensExpireIn = $date instanceof DateTimeInterface ? Carbon::now()->diff($date) : $date; - - return new static; } /** * Get or set when refresh tokens expire. - * - * @param \DateTimeInterface|\DateInterval|null $date - * @return \DateInterval|static */ - public static function refreshTokensExpireIn(DateTimeInterface|DateInterval $date = null) + public static function refreshTokensExpireIn(DateTimeInterface|DateInterval|null $date = null): DateInterval { if (is_null($date)) { - return static::$refreshTokensExpireIn ?? new DateInterval('P1Y'); + return static::$refreshTokensExpireIn ??= new DateInterval('P1Y'); } - static::$refreshTokensExpireIn = $date instanceof DateTimeInterface + return static::$refreshTokensExpireIn = $date instanceof DateTimeInterface ? Carbon::now()->diff($date) : $date; - - return new static; } /** * Get or set when personal access tokens expire. - * - * @param \DateTimeInterface|\DateInterval|null $date - * @return \DateInterval|static */ - public static function personalAccessTokensExpireIn(DateTimeInterface|DateInterval $date = null) + public static function personalAccessTokensExpireIn(DateTimeInterface|DateInterval|null $date = null): DateInterval { if (is_null($date)) { - return static::$personalAccessTokensExpireIn ?? new DateInterval('P1Y'); + return static::$personalAccessTokensExpireIn ??= new DateInterval('P1Y'); } - static::$personalAccessTokensExpireIn = $date instanceof DateTimeInterface + return static::$personalAccessTokensExpireIn = $date instanceof DateTimeInterface ? Carbon::now()->diff($date) : $date; - - return new static; } /** * Get or set the name for API token cookies. - * - * @param string|null $cookie - * @return string|static */ - public static function cookie($cookie = null) + public static function cookie(?string $cookie = null): string { if (is_null($cookie)) { return static::$cookie; } - static::$cookie = $cookie; - - return new static; + return static::$cookie = $cookie; } /** * Indicate that Passport should ignore incoming CSRF tokens. - * - * @param bool $ignoreCsrfToken - * @return static */ - public static function ignoreCsrfToken($ignoreCsrfToken = true) + public static function ignoreCsrfToken(bool $ignoreCsrfToken = true): void { static::$ignoreCsrfToken = $ignoreCsrfToken; - - return new static; } /** * Set the current user for the application with the given scopes. * - * @param \Illuminate\Contracts\Auth\Authenticatable|\Laravel\Passport\HasApiTokens $user - * @param array $scopes - * @param string $guard - * @return \Illuminate\Contracts\Auth\Authenticatable + * @template TUserModel of \Laravel\Passport\HasApiTokens + * + * @param TUserModel $user + * @param string[] $scopes + * @return TUserModel */ - public static function actingAs($user, $scopes = [], $guard = 'api') + public static function actingAs($user, array $scopes = [], ?string $guard = 'api') { $token = new AccessToken([ - 'oauth_user_id' => $user->getKey(), + 'oauth_user_id' => $user->getAuthIdentifier(), 'oauth_scopes' => $scopes, ]); @@ -418,12 +349,9 @@ public static function actingAs($user, $scopes = [], $guard = 'api') /** * Set the current client for the application with the given scopes. * - * @param \Laravel\Passport\Client $client - * @param array $scopes - * @param string $guard - * @return \Laravel\Passport\Client + * @param string[] $scopes */ - public static function actingAsClient($client, $scopes = [], $guard = 'api') + public static function actingAsClient(Client $client, array $scopes = [], ?string $guard = 'api'): Client { $mock = Mockery::mock(ResourceServer::class); $mock->shouldReceive('validateAuthenticatedRequest') @@ -443,22 +371,16 @@ public static function actingAsClient($client, $scopes = [], $guard = 'api') /** * Set the storage location of the encryption keys. - * - * @param string $path - * @return void */ - public static function loadKeysFrom($path) + public static function loadKeysFrom(string $path): void { static::$keyPath = $path; } /** * The location of the encryption keys. - * - * @param string $file - * @return string */ - public static function keyPath($file) + public static function keyPath(string $file): string { $file = ltrim($file, '/\\'); @@ -470,10 +392,9 @@ public static function keyPath($file) /** * Set the access token entity class name. * - * @param string $accessTokenEntity - * @return void + * @param class-string<\Laravel\Passport\Bridge\AccessToken> $accessTokenEntity */ - public static function useAccessTokenEntity($accessTokenEntity) + public static function useAccessTokenEntity(string $accessTokenEntity): void { static::$accessTokenEntity = $accessTokenEntity; } @@ -481,10 +402,9 @@ public static function useAccessTokenEntity($accessTokenEntity) /** * Set the auth code model class name. * - * @param string $authCodeModel - * @return void + * @param class-string<\Laravel\Passport\AuthCode> $authCodeModel */ - public static function useAuthCodeModel($authCodeModel) + public static function useAuthCodeModel(string $authCodeModel): void { static::$authCodeModel = $authCodeModel; } @@ -492,19 +412,17 @@ public static function useAuthCodeModel($authCodeModel) /** * Get the auth code model class name. * - * @return string + * @return class-string<\Laravel\Passport\AuthCode> */ - public static function authCodeModel() + public static function authCodeModel(): string { return static::$authCodeModel; } /** * Get a new auth code model instance. - * - * @return \Laravel\Passport\AuthCode */ - public static function authCode() + public static function authCode(): AuthCode { return new static::$authCodeModel; } @@ -512,10 +430,9 @@ public static function authCode() /** * Set the client model class name. * - * @param string $clientModel - * @return void + * @param class-string<\Laravel\Passport\Client> $clientModel */ - public static function useClientModel($clientModel) + public static function useClientModel(string $clientModel): void { static::$clientModel = $clientModel; } @@ -523,19 +440,17 @@ public static function useClientModel($clientModel) /** * Get the client model class name. * - * @return string + * @return class-string<\Laravel\Passport\Client> */ - public static function clientModel() + public static function clientModel(): string { return static::$clientModel; } /** * Get a new client model instance. - * - * @return \Laravel\Passport\Client */ - public static function client() + public static function client(): Client { return new static::$clientModel; } @@ -543,10 +458,9 @@ public static function client() /** * Set the token model class name. * - * @param string $tokenModel - * @return void + * @param class-string<\Laravel\Passport\Token> $tokenModel */ - public static function useTokenModel($tokenModel) + public static function useTokenModel(string $tokenModel): void { static::$tokenModel = $tokenModel; } @@ -554,19 +468,17 @@ public static function useTokenModel($tokenModel) /** * Get the token model class name. * - * @return string + * @return class-string<\Laravel\Passport\Token> */ - public static function tokenModel() + public static function tokenModel(): string { return static::$tokenModel; } /** * Get a new personal access client model instance. - * - * @return \Laravel\Passport\Token */ - public static function token() + public static function token(): Token { return new static::$tokenModel; } @@ -574,10 +486,9 @@ public static function token() /** * Set the refresh token model class name. * - * @param string $refreshTokenModel - * @return void + * @param class-string<\Laravel\Passport\RefreshToken> $refreshTokenModel */ - public static function useRefreshTokenModel($refreshTokenModel) + public static function useRefreshTokenModel(string $refreshTokenModel): void { static::$refreshTokenModel = $refreshTokenModel; } @@ -585,19 +496,17 @@ public static function useRefreshTokenModel($refreshTokenModel) /** * Get the refresh token model class name. * - * @return string + * @return class-string<\Laravel\Passport\RefreshToken> */ - public static function refreshTokenModel() + public static function refreshTokenModel(): string { return static::$refreshTokenModel; } /** * Get a new refresh token model instance. - * - * @return \Laravel\Passport\RefreshToken */ - public static function refreshToken() + public static function refreshToken(): RefreshToken { return new static::$refreshTokenModel; } @@ -605,27 +514,21 @@ public static function refreshToken() /** * Specify the callback that should be invoked to generate encryption keys for encrypting JWT tokens. * - * @param callable $callback - * @return static + * @param (\Closure(\Illuminate\Contracts\Encryption\Encrypter): string)|null $callback */ - public static function encryptTokensUsing($callback) + public static function encryptTokensUsing(?Closure $callback): void { static::$tokenEncryptionKeyCallback = $callback; - - return new static; } /** * Generate an encryption key for encrypting JWT tokens. - * - * @param \Illuminate\Contracts\Encryption\Encrypter $encrypter - * @return string */ - public static function tokenEncryptionKey(Encrypter $encrypter) + public static function tokenEncryptionKey(Encrypter $encrypter): string { - return is_callable(static::$tokenEncryptionKeyCallback) ? - (static::$tokenEncryptionKeyCallback)($encrypter) : - $encrypter->getKey(); + return is_callable(static::$tokenEncryptionKeyCallback) + ? (static::$tokenEncryptionKeyCallback)($encrypter) + : $encrypter->getKey(); } /** @@ -646,6 +549,8 @@ public static function viewPrefix(string $prefix): void /** * Specify which view should be used as the authorization view. + * + * @param (\Closure(array): (\Symfony\Component\HttpFoundation\Response))|string $view */ public static function authorizationView(Closure|string $view): void { @@ -654,61 +559,41 @@ public static function authorizationView(Closure|string $view): void /** * Configure Passport to not register its routes. - * - * @return static */ - public static function ignoreRoutes() + public static function ignoreRoutes(): void { static::$registersRoutes = false; - - return new static; } /** * Instruct Passport to enable cookie serialization. - * - * @return static */ - public static function withCookieSerialization() + public static function withCookieSerialization(): void { static::$unserializesCookies = true; - - return new static; } /** * Instruct Passport to disable cookie serialization. - * - * @return static */ - public static function withoutCookieSerialization() + public static function withoutCookieSerialization(): void { static::$unserializesCookies = false; - - return new static; } /** * Instruct Passport to enable cookie encryption. - * - * @return static */ - public static function withCookieEncryption() + public static function withCookieEncryption(): void { static::$decryptsCookies = true; - - return new static; } /** * Instruct Passport to disable cookie encryption. - * - * @return static */ - public static function withoutCookieEncryption() + public static function withoutCookieEncryption(): void { static::$decryptsCookies = false; - - return new static; } } diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 9c96f22b1..d2abfd450 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -4,7 +4,6 @@ use DateInterval; use Illuminate\Auth\Events\Logout; -use Illuminate\Config\Repository as Config; use Illuminate\Contracts\Auth\StatefulGuard; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Cookie; @@ -32,10 +31,8 @@ class PassportServiceProvider extends ServiceProvider { /** * Bootstrap the application services. - * - * @return void */ - public function boot() + public function boot(): void { $this->registerRoutes(); $this->registerPublishing(); @@ -46,10 +43,8 @@ public function boot() /** * Register the Passport routes. - * - * @return void */ - protected function registerRoutes() + protected function registerRoutes(): void { if (Passport::$registersRoutes) { Route::group([ @@ -64,10 +59,8 @@ protected function registerRoutes() /** * Register the package's publishable resources. - * - * @return void */ - protected function registerPublishing() + protected function registerPublishing(): void { if ($this->app->runningInConsole()) { $publishesMigrationsMethod = method_exists($this, 'publishesMigrations') @@ -86,10 +79,8 @@ protected function registerPublishing() /** * Register the Passport Artisan commands. - * - * @return void */ - protected function registerCommands() + protected function registerCommands(): void { if ($this->app->runningInConsole()) { $this->commands([ @@ -104,10 +95,8 @@ protected function registerCommands() /** * Register the service provider. - * - * @return void */ - public function register() + public function register(): void { $this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport'); @@ -125,13 +114,11 @@ public function register() /** * Register the authorization server. - * - * @return void */ - protected function registerAuthorizationServer() + protected function registerAuthorizationServer(): void { $this->app->singleton(AuthorizationServer::class, function () { - return tap($this->makeAuthorizationServer(), function ($server) { + return tap($this->makeAuthorizationServer(), function (AuthorizationServer $server) { $server->setDefaultScope(Passport::$defaultScope); $server->enableGrantType( @@ -167,22 +154,18 @@ protected function registerAuthorizationServer() /** * Create and configure an instance of the Auth Code grant. - * - * @return \League\OAuth2\Server\Grant\AuthCodeGrant */ - protected function makeAuthCodeGrant() + protected function makeAuthCodeGrant(): AuthCodeGrant { - return tap($this->buildAuthCodeGrant(), function ($grant) { + return tap($this->buildAuthCodeGrant(), function (AuthCodeGrant $grant) { $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn()); }); } /** * Build the Auth Code grant instance. - * - * @return \League\OAuth2\Server\Grant\AuthCodeGrant */ - protected function buildAuthCodeGrant() + protected function buildAuthCodeGrant(): AuthCodeGrant { return new AuthCodeGrant( $this->app->make(Bridge\AuthCodeRepository::class), @@ -193,72 +176,58 @@ protected function buildAuthCodeGrant() /** * Create and configure a Refresh Token grant instance. - * - * @return \League\OAuth2\Server\Grant\RefreshTokenGrant */ - protected function makeRefreshTokenGrant() + protected function makeRefreshTokenGrant(): RefreshTokenGrant { $repository = $this->app->make(RefreshTokenRepository::class); - return tap(new RefreshTokenGrant($repository), function ($grant) { + return tap(new RefreshTokenGrant($repository), function (RefreshTokenGrant $grant) { $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn()); }); } /** * Create and configure a Password grant instance. - * - * @return \League\OAuth2\Server\Grant\PasswordGrant */ - protected function makePasswordGrant() + protected function makePasswordGrant(): PasswordGrant { - $grant = new PasswordGrant( + return tap(new PasswordGrant( $this->app->make(Bridge\UserRepository::class), $this->app->make(Bridge\RefreshTokenRepository::class) - ); - - $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn()); - - return $grant; + ), function (PasswordGrant $grant) { + $grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn()); + }); } /** * Create and configure an instance of the Implicit grant. - * - * @return \League\OAuth2\Server\Grant\ImplicitGrant */ - protected function makeImplicitGrant() + protected function makeImplicitGrant(): ImplicitGrant { return new ImplicitGrant(Passport::tokensExpireIn()); } /** * Make the authorization service instance. - * - * @return \League\OAuth2\Server\AuthorizationServer */ - public function makeAuthorizationServer() + public function makeAuthorizationServer(): AuthorizationServer { return new AuthorizationServer( $this->app->make(Bridge\ClientRepository::class), $this->app->make(Bridge\AccessTokenRepository::class), $this->app->make(Bridge\ScopeRepository::class), $this->makeCryptKey('private'), - app('encrypter')->getKey(), + $this->app->make('encrypter')->getKey(), Passport::$authorizationServerResponseType ); } /** * Register the JWT Parser. - * - * @return void */ - protected function registerJWTParser() + protected function registerJWTParser(): void { - $this->app->singleton(ParserContract::class, function () { - return new Parser(new JoseEncoder); - }); + $this->app->singleton(ParserContract::class, fn () => new Parser(new JoseEncoder)); } /** @@ -266,25 +235,20 @@ protected function registerJWTParser() * * @return void */ - protected function registerResourceServer() + protected function registerResourceServer(): void { - $this->app->singleton(ResourceServer::class, function ($container) { - return new ResourceServer( - $container->make(Bridge\AccessTokenRepository::class), - $this->makeCryptKey('public') - ); - }); + $this->app->singleton(ResourceServer::class, fn ($container) => new ResourceServer( + $container->make(Bridge\AccessTokenRepository::class), + $this->makeCryptKey('public') + )); } /** * Create a CryptKey instance. - * - * @param string $type - * @return \League\OAuth2\Server\CryptKey */ - protected function makeCryptKey($type) + protected function makeCryptKey(string $type): CryptKey { - $key = str_replace('\\n', "\n", $this->app->make(Config::class)->get('passport.'.$type.'_key') ?? ''); + $key = str_replace('\\n', "\n", config("passport.{$type}_key") ?? ''); if (! $key) { $key = 'file://'.Passport::keyPath('oauth-'.$type.'.key'); @@ -295,27 +259,22 @@ protected function makeCryptKey($type) /** * Register the token guard. - * - * @return void */ - protected function registerGuard() + protected function registerGuard(): void { Auth::resolved(function ($auth) { - $auth->extend('passport', function ($app, $name, array $config) { - return tap($this->makeGuard($config), function ($guard) { - app()->refresh('request', $guard, 'setRequest'); - }); - }); + $auth->extend('passport', fn ($app, $name, array $config) => tap($this->makeGuard($config), function ($guard) { + app()->refresh('request', $guard, 'setRequest'); + })); }); } /** * Make an instance of the token guard. * - * @param array $config - * @return \Laravel\Passport\Guards\TokenGuard + * @param array $config */ - protected function makeGuard(array $config) + protected function makeGuard(array $config): TokenGuard { return new TokenGuard( $this->app->make(ResourceServer::class), @@ -328,10 +287,8 @@ protected function makeGuard(array $config) /** * Register the cookie deletion event handler. - * - * @return void */ - protected function deleteCookieOnLogout() + protected function deleteCookieOnLogout(): void { Event::listen(Logout::class, function () { if (Request::hasCookie(Passport::cookie())) { diff --git a/src/PassportUserProvider.php b/src/PassportUserProvider.php index 325a01663..7fceb307f 100644 --- a/src/PassportUserProvider.php +++ b/src/PassportUserProvider.php @@ -7,37 +7,19 @@ class PassportUserProvider implements UserProvider { - /** - * The user provider instance. - * - * @var \Illuminate\Contracts\Auth\UserProvider - */ - protected $provider; - - /** - * The user provider name. - * - * @var string - */ - protected $providerName; - /** * Create a new passport user provider. - * - * @param \Illuminate\Contracts\Auth\UserProvider $provider - * @param string $providerName - * @return void */ - public function __construct(UserProvider $provider, $providerName) - { - $this->provider = $provider; - $this->providerName = $providerName; + public function __construct( + protected UserProvider $provider, + protected string $providerName + ) { } /** * {@inheritdoc} */ - public function retrieveById($identifier) + public function retrieveById($identifier): ?Authenticatable { return $this->provider->retrieveById($identifier); } @@ -45,7 +27,7 @@ public function retrieveById($identifier) /** * {@inheritdoc} */ - public function retrieveByToken($identifier, $token) + public function retrieveByToken($identifier, $token): ?Authenticatable { return $this->provider->retrieveByToken($identifier, $token); } @@ -53,7 +35,7 @@ public function retrieveByToken($identifier, $token) /** * {@inheritdoc} */ - public function updateRememberToken(Authenticatable $user, $token) + public function updateRememberToken(Authenticatable $user, $token): void { $this->provider->updateRememberToken($user, $token); } @@ -61,7 +43,7 @@ public function updateRememberToken(Authenticatable $user, $token) /** * {@inheritdoc} */ - public function retrieveByCredentials(array $credentials) + public function retrieveByCredentials(array $credentials): ?Authenticatable { return $this->provider->retrieveByCredentials($credentials); } @@ -69,7 +51,7 @@ public function retrieveByCredentials(array $credentials) /** * {@inheritdoc} */ - public function validateCredentials(Authenticatable $user, array $credentials) + public function validateCredentials(Authenticatable $user, array $credentials): bool { return $this->provider->validateCredentials($user, $credentials); } @@ -77,17 +59,15 @@ public function validateCredentials(Authenticatable $user, array $credentials) /** * {@inheritdoc} */ - public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false) + public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void { $this->provider->rehashPasswordIfRequired($user, $credentials, $force); } /** * Get the name of the user provider. - * - * @return string */ - public function getProviderName() + public function getProviderName(): string { return $this->providerName; } diff --git a/src/PersonalAccessTokenFactory.php b/src/PersonalAccessTokenFactory.php index bedfde479..cdc168566 100644 --- a/src/PersonalAccessTokenFactory.php +++ b/src/PersonalAccessTokenFactory.php @@ -10,64 +10,30 @@ class PersonalAccessTokenFactory { - /** - * The authorization server instance. - * - * @var \League\OAuth2\Server\AuthorizationServer - */ - protected $server; - - /** - * The token repository instance. - * - * @var \Laravel\Passport\TokenRepository - */ - protected $tokens; - - /** - * The JWT token parser instance. - * - * @var \Lcobucci\JWT\Parser - */ - protected $jwt; - /** * Create a new personal access token factory instance. - * - * @param \League\OAuth2\Server\AuthorizationServer $server - * @param \Laravel\Passport\TokenRepository $tokens - * @param \Lcobucci\JWT\Parser $jwt - * @return void */ - public function __construct(AuthorizationServer $server, - TokenRepository $tokens, - JwtParser $jwt) - { - $this->jwt = $jwt; - $this->tokens = $tokens; - $this->server = $server; + public function __construct( + protected AuthorizationServer $server, + protected JwtParser $jwt + ) { } /** * Create a new personal access token. * - * @param mixed $userId - * @param string $name * @param string[] $scopes - * @param string $provider - * @return \Laravel\Passport\PersonalAccessTokenResult */ - public function make($userId, string $name, array $scopes, string $provider) + public function make(string|int $userId, string $name, array $scopes, string $provider): PersonalAccessTokenResult { $response = $this->dispatchRequestToAuthorizationServer( $this->createRequest($userId, $scopes, $provider) ); - $token = tap($this->findAccessToken($response), function ($token) use ($userId, $name) { - $this->tokens->save($token->forceFill([ - 'user_id' => $userId, + $token = tap($this->findAccessToken($response), function (Token $token) use ($name) { + $token->forceFill([ 'name' => $name, - ])); + ])->save(); }); return new PersonalAccessTokenResult( @@ -78,12 +44,9 @@ public function make($userId, string $name, array $scopes, string $provider) /** * Create a request instance for the given client. * - * @param mixed $userId * @param string[] $scopes - * @param string $provider - * @return \Psr\Http\Message\ServerRequestInterface */ - protected function createRequest($userId, array $scopes, string $provider) + protected function createRequest(string|int $userId, array $scopes, string $provider): ServerRequestInterface { return (new ServerRequest('POST', 'not-important'))->withParsedBody([ 'grant_type' => 'personal_access', @@ -96,10 +59,9 @@ protected function createRequest($userId, array $scopes, string $provider) /** * Dispatch the given request to the authorization server. * - * @param \Psr\Http\Message\ServerRequestInterface $request - * @return array + * @return array */ - protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $request) + protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $request): array { return json_decode($this->server->respondToAccessTokenRequest( $request, new Response @@ -109,12 +71,11 @@ protected function dispatchRequestToAuthorizationServer(ServerRequestInterface $ /** * Get the access token instance for the parsed response. * - * @param array $response - * @return \Laravel\Passport\Token + * @param array $response */ - public function findAccessToken(array $response) + public function findAccessToken(array $response): Token { - return $this->tokens->find( + return Passport::token()->newQuery()->find( $this->jwt->parse($response['access_token'])->claims()->get('jti') ); } diff --git a/src/PersonalAccessTokenResult.php b/src/PersonalAccessTokenResult.php index 8a6627994..0e92898f0 100644 --- a/src/PersonalAccessTokenResult.php +++ b/src/PersonalAccessTokenResult.php @@ -7,39 +7,21 @@ class PersonalAccessTokenResult implements Arrayable, Jsonable { - /** - * The access token. - * - * @var string - */ - public $accessToken; - - /** - * The token model instance. - * - * @var \Laravel\Passport\Token - */ - public $token; - /** * Create a new result instance. - * - * @param string $accessToken - * @param \Laravel\Passport\Token $token - * @return void */ - public function __construct($accessToken, $token) - { - $this->token = $token; - $this->accessToken = $accessToken; + public function __construct( + public string $accessToken, + public Token $token + ) { } /** * Get the instance as an array. * - * @return array + * @return array */ - public function toArray() + public function toArray(): array { return [ 'accessToken' => $this->accessToken, @@ -51,9 +33,8 @@ public function toArray() * Convert the object to its JSON representation. * * @param int $options - * @return string */ - public function toJson($options = 0) + public function toJson($options = 0): string { return json_encode($this->toArray(), $options); } diff --git a/src/RefreshToken.php b/src/RefreshToken.php index 6b4087938..9b8558444 100644 --- a/src/RefreshToken.php +++ b/src/RefreshToken.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class RefreshToken extends Model { @@ -30,14 +31,14 @@ class RefreshToken extends Model /** * The guarded attributes on the model. * - * @var array + * @var array|bool */ - protected $guarded = []; + protected $guarded = false; /** * The attributes that should be cast to native types. * - * @var array + * @var array */ protected $casts = [ 'revoked' => 'bool', @@ -54,29 +55,25 @@ class RefreshToken extends Model /** * Get the access token that the refresh token belongs to. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\Laravel\Passport\Token, $this> */ - public function accessToken() + public function accessToken(): BelongsTo { return $this->belongsTo(Passport::tokenModel()); } /** * Revoke the token instance. - * - * @return bool */ - public function revoke() + public function revoke(): bool { return $this->forceFill(['revoked' => true])->save(); } /** * Get the current connection name for the model. - * - * @return string|null */ - public function getConnectionName() + public function getConnectionName(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/src/Scope.php b/src/Scope.php index 127b6789f..45c6c510d 100644 --- a/src/Scope.php +++ b/src/Scope.php @@ -7,39 +7,21 @@ class Scope implements Arrayable, Jsonable { - /** - * The name / ID of the scope. - * - * @var string - */ - public $id; - - /** - * The scope description. - * - * @var string - */ - public $description; - /** * Create a new scope instance. - * - * @param string $id - * @param string $description - * @return void */ - public function __construct($id, $description) - { - $this->id = $id; - $this->description = $description; + public function __construct( + public string $id, + public string $description + ) { } /** * Get the instance as an array. * - * @return array + * @return array */ - public function toArray() + public function toArray(): array { return [ 'id' => $this->id, @@ -51,9 +33,8 @@ public function toArray() * Convert the object to its JSON representation. * * @param int $options - * @return string */ - public function toJson($options = 0) + public function toJson($options = 0): string { return json_encode($this->toArray(), $options); } diff --git a/src/Token.php b/src/Token.php index a917eb49c..b4339f20c 100644 --- a/src/Token.php +++ b/src/Token.php @@ -3,6 +3,8 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasOne; class Token extends Model { @@ -30,14 +32,14 @@ class Token extends Model /** * The guarded attributes on the model. * - * @var array + * @var array|bool */ - protected $guarded = []; + protected $guarded = false; /** * The attributes that should be cast to native types. * - * @var array + * @var array */ protected $casts = [ 'scopes' => 'array', @@ -48,9 +50,9 @@ class Token extends Model /** * Get the client that the token belongs to. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\Laravel\Passport\Client, $this> */ - public function client() + public function client(): BelongsTo { return $this->belongsTo(Passport::clientModel()); } @@ -58,9 +60,9 @@ public function client() /** * Get the refresh token associated with the token. * - * @return \Illuminate\Database\Eloquent\Relations\HasOne + * @return \Illuminate\Database\Eloquent\Relations\HasOne<\Laravel\Passport\RefreshToken, $this> */ - public function refreshToken() + public function refreshToken(): HasOne { return $this->hasOne(Passport::refreshTokenModel(), 'access_token_id'); } @@ -70,33 +72,29 @@ public function refreshToken() * * @deprecated Will be removed in a future Laravel version. * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\Illuminate\Foundation\Auth\User, $this> */ - public function user() + public function user(): BelongsTo { $provider = $this->client->provider ?: config('auth.guards.api.provider'); $model = config('auth.providers.'.$provider.'.model'); - return $this->belongsTo($model, 'user_id', (new $model)->getKeyName()); + return $this->belongsTo($model, 'user_id', (new $model)->getAuthIdentifierName()); } /** * Revoke the token instance. - * - * @return bool */ - public function revoke() + public function revoke(): bool { return $this->forceFill(['revoked' => true])->save(); } /** * Get the current connection name for the model. - * - * @return string|null */ - public function getConnectionName() + public function getConnectionName(): ?string { return $this->connection ?? config('passport.connection'); } diff --git a/tests/Feature/ActingAsTest.php b/tests/Feature/ActingAsTest.php index d67f93798..62617bc9b 100644 --- a/tests/Feature/ActingAsTest.php +++ b/tests/Feature/ActingAsTest.php @@ -55,11 +55,17 @@ public function testItCanGenerateDefinitionViaStaticMethod() $signature = (string) CheckScopes::using('admin', 'footest'); $this->assertSame('Laravel\Passport\Http\Middleware\CheckScopes:admin,footest', $signature); + $signature = (string) CheckScopes::using(['admin', 'footest']); + $this->assertSame('Laravel\Passport\Http\Middleware\CheckScopes:admin,footest', $signature); + $signature = (string) CheckForAnyScope::using('admin'); $this->assertSame('Laravel\Passport\Http\Middleware\CheckForAnyScope:admin', $signature); $signature = (string) CheckForAnyScope::using('admin', 'footest'); $this->assertSame('Laravel\Passport\Http\Middleware\CheckForAnyScope:admin,footest', $signature); + + $signature = (string) CheckForAnyScope::using(['admin', 'footest']); + $this->assertSame('Laravel\Passport\Http\Middleware\CheckForAnyScope:admin,footest', $signature); } public function testActingAsWhenTheRouteIsProtectedByCheckForAnyScopeMiddleware() diff --git a/tests/Unit/BridgeAccessTokenRepositoryTest.php b/tests/Feature/BridgeAccessTokenRepositoryTest.php similarity index 54% rename from tests/Unit/BridgeAccessTokenRepositoryTest.php rename to tests/Feature/BridgeAccessTokenRepositoryTest.php index cd2e982e2..4b14a11d9 100644 --- a/tests/Unit/BridgeAccessTokenRepositoryTest.php +++ b/tests/Feature/BridgeAccessTokenRepositoryTest.php @@ -1,81 +1,76 @@ shouldReceive('create')->once()->andReturnUsing(function ($array) use ($expiration) { - $this->assertEquals(1, $array['id']); - $this->assertEquals(2, $array['user_id']); - $this->assertEquals('client-id', $array['client_id']); - $this->assertEquals(['scopes'], $array['scopes']); - $this->assertEquals(false, $array['revoked']); - $this->assertInstanceOf(DateTime::class, $array['created_at']); - $this->assertInstanceOf(DateTime::class, $array['updated_at']); - $this->assertEquals($expiration, $array['expires_at']); - }); - $events->shouldReceive('dispatch')->once(); $accessToken = new AccessToken(2, [new Scope('scopes')], new Client('client-id', 'name', ['redirect'])); $accessToken->setIdentifier(1); $accessToken->setExpiryDateTime($expiration); - $repository = new AccessTokenRepository($tokenRepository, $events); + $repository = new AccessTokenRepository($events); $repository->persistNewAccessToken($accessToken); + + $this->assertDatabaseHas('oauth_access_tokens', [ + 'id' => '1', + 'user_id' => '2', + 'client_id' => 'client-id', + 'scopes' => '["scopes"]', + 'revoked' => false, + 'expires_at' => $expiration, + ]); } public function test_access_tokens_can_be_revoked() { - $tokenRepository = m::mock(TokenRepository::class); $events = m::mock(Dispatcher::class); + $events->shouldReceive('dispatch')->twice(); - $tokenRepository->shouldReceive('revokeAccessToken')->with('token-id')->once()->andReturn(1); - $events->shouldReceive('dispatch')->once(); + $accessToken = new AccessToken(2, [], new Client('client-id', 'name', ['redirect'])); + $accessToken->setIdentifier('token-id'); + $accessToken->setExpiryDateTime(CarbonImmutable::now()); + + $repository = new AccessTokenRepository($events); + $repository->persistNewAccessToken($accessToken); - $repository = new AccessTokenRepository($tokenRepository, $events); $repository->revokeAccessToken('token-id'); } public function test_access_token_revoke_event_is_not_dispatched_when_nothing_happened() { - $tokenRepository = m::mock(TokenRepository::class); $events = m::mock(Dispatcher::class); - - $tokenRepository->shouldReceive('revokeAccessToken')->with('token-id')->once()->andReturn(0); $events->shouldNotReceive('dispatch'); - $repository = new AccessTokenRepository($tokenRepository, $events); + $repository = new AccessTokenRepository($events); $repository->revokeAccessToken('token-id'); } public function test_can_get_new_access_token() { - $tokenRepository = m::mock(TokenRepository::class); $events = m::mock(Dispatcher::class); - $repository = new AccessTokenRepository($tokenRepository, $events); + $repository = new AccessTokenRepository($events); $client = new Client('client-id', 'name', ['redirect']); $scopes = [new Scope('place-orders'), new Scope('check-status')]; $userIdentifier = 123; diff --git a/tests/Unit/BridgeRefreshTokenRepositoryTest.php b/tests/Feature/BridgeRefreshTokenRepositoryTest.php similarity index 56% rename from tests/Unit/BridgeRefreshTokenRepositoryTest.php rename to tests/Feature/BridgeRefreshTokenRepositoryTest.php index 139406320..0cec97196 100644 --- a/tests/Unit/BridgeRefreshTokenRepositoryTest.php +++ b/tests/Feature/BridgeRefreshTokenRepositoryTest.php @@ -1,36 +1,28 @@ shouldReceive('create')->once()->andReturnUsing(function ($array) use ($expiration) { - $this->assertEquals('1', $array['id']); - $this->assertEquals('2', $array['access_token_id']); - $this->assertFalse($array['revoked']); - $this->assertEquals($expiration, $array['expires_at']); - }); - $events->shouldReceive('dispatch')->once(); $accessToken = new AccessToken('3', [], m::mock(Client::class)); @@ -41,16 +33,22 @@ public function test_access_tokens_can_be_persisted() $refreshToken->setExpiryDateTime($expiration); $refreshToken->setAccessToken($accessToken); - $repository = new BridgeRefreshTokenRepository($refreshTokenRepository, $events); + $repository = new RefreshTokenRepository($events); $repository->persistNewRefreshToken($refreshToken); + + $this->assertDatabaseHas('oauth_refresh_tokens', [ + 'id' => '1', + 'access_token_id' => '2', + 'revoked' => false, + 'expires_at' => $expiration, + ]); } public function test_can_get_new_refresh_token() { - $refreshTokenRepository = m::mock(RefreshTokenRepository::class); $events = m::mock(Dispatcher::class); - $repository = new BridgeRefreshTokenRepository($refreshTokenRepository, $events); + $repository = new RefreshTokenRepository($events); $token = $repository->getNewRefreshToken(); diff --git a/tests/Feature/PassportServiceProviderTest.php b/tests/Feature/PassportServiceProviderTest.php new file mode 100644 index 000000000..37ccab418 --- /dev/null +++ b/tests/Feature/PassportServiceProviderTest.php @@ -0,0 +1,56 @@ + $privateKeyString]); + + $provider = new PassportServiceProvider($this->app); + + // Call protected makeCryptKey method + $cryptKey = (fn () => $this->makeCryptKey('private'))->call($provider); + + $this->assertSame( + $privateKeyString, + $cryptKey->getKeyContents() + ); + } + + public function test_can_use_crypto_keys_from_local_disk() + { + Passport::loadKeysFrom(__DIR__.'/../keys'); + + $privateKey = openssl_pkey_new(); + + openssl_pkey_export_to_file($privateKey, __DIR__.'/../keys/oauth-private.key'); + openssl_pkey_export($privateKey, $privateKeyString); + chmod(__DIR__.'/../keys/oauth-private.key', 0600); + + config(['passport.private_key' => null]); + + $provider = new PassportServiceProvider($this->app); + + // Call protected makeCryptKey method + $cryptKey = (fn () => $this->makeCryptKey('private'))->call($provider); + + $this->assertSame( + $privateKeyString, + file_get_contents($cryptKey->getKeyPath()) + ); + } +} diff --git a/tests/Feature/PersonalAccessGrantTest.php b/tests/Feature/PersonalAccessGrantTest.php index ed53edce3..3a9a0fe05 100644 --- a/tests/Feature/PersonalAccessGrantTest.php +++ b/tests/Feature/PersonalAccessGrantTest.php @@ -34,6 +34,13 @@ public function testIssueToken() $this->assertSame($client->getKey(), $result->token->client_id); $this->assertSame($user->getAuthIdentifier(), $result->token->user_id); $this->assertSame(['bar'], $result->token->scopes); + + $this->assertDatabaseHas('oauth_access_tokens', [ + 'id' => $result->token->id, + 'user_id' => $result->token->user_id, + 'client_id' => $result->token->client_id, + 'name' => $result->token->name, + ]); } public function testIssueTokenWithDifferentProviders() diff --git a/tests/Feature/RevokedTest.php b/tests/Feature/RevokedTest.php index 2ba758967..9a61f3dc4 100644 --- a/tests/Feature/RevokedTest.php +++ b/tests/Feature/RevokedTest.php @@ -7,9 +7,7 @@ use Laravel\Passport\Bridge\AuthCodeRepository as BridgeAuthCodeRepository; use Laravel\Passport\Bridge\RefreshToken; use Laravel\Passport\Bridge\RefreshTokenRepository as BridgeRefreshTokenRepository; -use Laravel\Passport\RefreshTokenRepository; use Laravel\Passport\Tests\Feature\PassportTestCase; -use Laravel\Passport\TokenRepository; use Mockery as m; use Orchestra\Testbench\Concerns\WithLaravelMigrations; @@ -97,7 +95,7 @@ private function accessTokenRepository(): BridgeAccessTokenRepository $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); $events->shouldReceive('dispatch'); - return new BridgeAccessTokenRepository(new TokenRepository, $events); + return new BridgeAccessTokenRepository($events); } private function persistNewAccessToken(BridgeAccessTokenRepository $repository, string $id): void @@ -134,7 +132,7 @@ private function refreshTokenRepository(): BridgeRefreshTokenRepository $events = m::mock('Illuminate\Contracts\Events\Dispatcher'); $events->shouldReceive('dispatch'); - return new BridgeRefreshTokenRepository(new RefreshTokenRepository, $events); + return new BridgeRefreshTokenRepository($events); } private function persistNewRefreshToken(BridgeRefreshTokenRepository $repository, string $id): void diff --git a/tests/Unit/AuthorizationControllerTest.php b/tests/Unit/AuthorizationControllerTest.php index 876ebe711..0dff23dd0 100644 --- a/tests/Unit/AuthorizationControllerTest.php +++ b/tests/Unit/AuthorizationControllerTest.php @@ -38,8 +38,6 @@ public function test_authorization_view_is_presented() $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock(Authenticatable::class)); $server->shouldReceive('validateAuthorizationRequest')->andReturn($authRequest = m::mock(AuthorizationRequestInterface::class)); @@ -70,8 +68,10 @@ public function test_authorization_view_is_presented() return $response; }); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $this->assertSame($response, $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request )); } @@ -81,8 +81,6 @@ public function test_authorization_exceptions_are_handled() $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->andThrow(LeagueException::invalidCredentials()); @@ -93,8 +91,10 @@ public function test_authorization_exceptions_are_handled() $this->expectException(OAuthServerException::class); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request ); } @@ -108,8 +108,6 @@ public function test_request_is_approved_if_valid_token_exists() $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock(Authenticatable::class)); $psrResponse = new Response(); @@ -139,8 +137,10 @@ public function test_request_is_approved_if_valid_token_exists() $client->shouldReceive('getKey')->andReturn(1); $client->shouldReceive('tokens->where->pluck')->andReturn(collect([['scope-1']])); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $this->assertSame('approved', $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request )->getContent()); } @@ -154,8 +154,6 @@ public function test_request_is_approved_if_client_can_skip_authorization() $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock(Authenticatable::class)); $psrResponse = new Response(); @@ -183,8 +181,10 @@ public function test_request_is_approved_if_client_can_skip_authorization() $client->shouldReceive('skipsAuthorization')->andReturn(true); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $this->assertSame('approved', $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request )->getContent()); } @@ -198,8 +198,6 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock()); $server->shouldReceive('validateAuthorizationRequest') @@ -228,8 +226,10 @@ public function test_authorization_view_is_presented_if_request_has_prompt_equal return $response; }); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $this->assertSame($response, $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request )); } @@ -245,8 +245,6 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $guard->shouldReceive('user')->andReturn($user = m::mock(Authenticatable::class)); $server->shouldReceive('validateAuthorizationRequest') @@ -275,8 +273,10 @@ public function test_authorization_denied_if_request_has_prompt_equals_to_none() $client->shouldReceive('getKey')->andReturn(1); $client->shouldReceive('tokens->where->pluck')->andReturn(collect()); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request ); } @@ -286,8 +286,6 @@ public function test_authorization_denied_if_unauthenticated_and_request_has_pro $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(true); $server->shouldReceive('validateAuthorizationRequest') ->andReturn($authRequest = m::mock(AuthorizationRequest::class)); @@ -306,9 +304,11 @@ public function test_authorization_denied_if_unauthenticated_and_request_has_pro $clients = m::mock(ClientRepository::class); + $controller = new AuthorizationController($server, $guard, $response, $clients); + try { $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request ); } catch (\Laravel\Passport\Exceptions\OAuthServerException $e) { $this->assertStringStartsWith( @@ -326,8 +326,6 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(false); $server->shouldReceive('validateAuthorizationRequest')->once(); $guard->shouldReceive('logout')->once(); @@ -343,8 +341,10 @@ public function test_logout_and_prompt_login_if_request_has_prompt_equals_to_log $clients = m::mock(ClientRepository::class); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $controller->authorize( - m::mock(ServerRequestInterface::class), $request, $clients + m::mock(ServerRequestInterface::class), $request ); } @@ -356,8 +356,6 @@ public function test_user_should_be_authenticated() $response = m::mock(AuthorizationViewResponse::class); $guard = m::mock(StatefulGuard::class); - $controller = new AuthorizationController($server, $guard, $response); - $guard->shouldReceive('guest')->andReturn(true); $server->shouldReceive('validateAuthorizationRequest')->once(); @@ -370,6 +368,8 @@ public function test_user_should_be_authenticated() $clients = m::mock(ClientRepository::class); + $controller = new AuthorizationController($server, $guard, $response, $clients); + $controller->authorize( m::mock(ServerRequestInterface::class), $request, $clients ); diff --git a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php index 5cb6b5708..1c32a15b1 100644 --- a/tests/Unit/CheckClientCredentialsForAnyScopeTest.php +++ b/tests/Unit/CheckClientCredentialsForAnyScopeTest.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Tests\Unit; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentialsForAnyScope; use League\OAuth2\Server\Exception\OAuthServerException; @@ -33,10 +34,10 @@ public function test_request_is_passed_along_if_token_is_valid() $request->headers->set('Authorization', 'Bearer token'); $response = $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }); - $this->assertSame('response', $response); + $this->assertSame('response', $response->getContent()); } public function test_request_is_passed_along_if_token_has_any_required_scope() @@ -56,10 +57,10 @@ public function test_request_is_passed_along_if_token_has_any_required_scope() $request->headers->set('Authorization', 'Bearer token'); $response = $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'notfoo', 'bar', 'notbaz'); - $this->assertSame('response', $response); + $this->assertSame('response', $response->getContent()); } public function test_exception_is_thrown_when_oauth_throws_exception() diff --git a/tests/Unit/CheckClientCredentialsTest.php b/tests/Unit/CheckClientCredentialsTest.php index 0fe7b6909..6c69686e9 100644 --- a/tests/Unit/CheckClientCredentialsTest.php +++ b/tests/Unit/CheckClientCredentialsTest.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Tests\Unit; use Illuminate\Http\Request; +use Illuminate\Http\Response; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckClientCredentials; use League\OAuth2\Server\Exception\OAuthServerException; @@ -33,10 +34,10 @@ public function test_request_is_passed_along_if_token_is_valid() $request->headers->set('Authorization', 'Bearer token'); $response = $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }); - $this->assertSame('response', $response); + $this->assertSame('response', $response->getContent()); } public function test_request_is_passed_along_if_token_and_scope_are_valid() @@ -56,10 +57,10 @@ public function test_request_is_passed_along_if_token_and_scope_are_valid() $request->headers->set('Authorization', 'Bearer token'); $response = $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'see-profile'); - $this->assertSame('response', $response); + $this->assertSame('response', $response->getContent()); } public function test_exception_is_thrown_when_oauth_throws_exception() diff --git a/tests/Unit/CheckForAnyScopeTest.php b/tests/Unit/CheckForAnyScopeTest.php index b4937bf76..348b653cf 100644 --- a/tests/Unit/CheckForAnyScopeTest.php +++ b/tests/Unit/CheckForAnyScopeTest.php @@ -2,6 +2,8 @@ namespace Laravel\Passport\Tests\Unit; +use Illuminate\Http\Request; +use Illuminate\Http\Response; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckForAnyScope as CheckScopes; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -15,17 +17,17 @@ class CheckForAnyScopeTest extends TestCase public function test_request_is_passed_along_if_scopes_are_present_on_token() { $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('token')->andReturn($token = m::mock()); $user->shouldReceive('tokenCan')->with('foo')->andReturn(true); $user->shouldReceive('tokenCan')->with('bar')->andReturn(false); $response = $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); - $this->assertSame('response', $response); + $this->assertSame('response', $response->getContent()); } public function test_exception_is_thrown_if_token_doesnt_have_scope() @@ -33,14 +35,14 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() $this->expectException('Laravel\Passport\Exceptions\MissingScopeException'); $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('token')->andReturn($token = m::mock()); $user->shouldReceive('tokenCan')->with('foo')->andReturn(false); $user->shouldReceive('tokenCan')->with('bar')->andReturn(false); $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); } @@ -49,11 +51,11 @@ public function test_exception_is_thrown_if_no_authenticated_user() $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->once()->andReturn(null); $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); } @@ -62,12 +64,12 @@ public function test_exception_is_thrown_if_no_token() $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('token')->andReturn(null); $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); } } diff --git a/tests/Unit/CheckScopesTest.php b/tests/Unit/CheckScopesTest.php index cc75b0138..5531717d0 100644 --- a/tests/Unit/CheckScopesTest.php +++ b/tests/Unit/CheckScopesTest.php @@ -2,6 +2,8 @@ namespace Laravel\Passport\Tests\Unit; +use Illuminate\Http\Request; +use Illuminate\Http\Response; use Laravel\Passport\Exceptions\AuthenticationException; use Laravel\Passport\Http\Middleware\CheckScopes; use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration; @@ -15,17 +17,17 @@ class CheckScopesTest extends TestCase public function test_request_is_passed_along_if_scopes_are_present_on_token() { $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('token')->andReturn($token = m::mock()); $user->shouldReceive('tokenCan')->with('foo')->andReturn(true); $user->shouldReceive('tokenCan')->with('bar')->andReturn(true); $response = $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); - $this->assertSame('response', $response); + $this->assertSame('response', $response->getContent()); } public function test_exception_is_thrown_if_token_doesnt_have_scope() @@ -33,13 +35,13 @@ public function test_exception_is_thrown_if_token_doesnt_have_scope() $this->expectException('Laravel\Passport\Exceptions\MissingScopeException'); $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('token')->andReturn($token = m::mock()); $user->shouldReceive('tokenCan')->with('foo')->andReturn(false); $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); } @@ -48,11 +50,11 @@ public function test_exception_is_thrown_if_no_authenticated_user() $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->once()->andReturn(null); $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); } @@ -61,12 +63,12 @@ public function test_exception_is_thrown_if_no_token() $this->expectException(AuthenticationException::class); $middleware = new CheckScopes; - $request = m::mock(); + $request = m::mock(Request::class); $request->shouldReceive('user')->andReturn($user = m::mock()); $user->shouldReceive('token')->andReturn(null); $middleware->handle($request, function () { - return 'response'; + return new Response('response'); }, 'foo', 'bar'); } } diff --git a/tests/Unit/PassportServiceProviderTest.php b/tests/Unit/PassportServiceProviderTest.php deleted file mode 100644 index f4ad54592..000000000 --- a/tests/Unit/PassportServiceProviderTest.php +++ /dev/null @@ -1,77 +0,0 @@ -shouldReceive('get') - ->with('passport.private_key') - ->andReturn($privateKeyString); - }); - - $provider = new PassportServiceProvider( - m::mock(App::class, ['make' => $config]) - ); - - // Call protected makeCryptKey method - $cryptKey = (function () { - return $this->makeCryptKey('private'); - })->call($provider); - - $this->assertSame( - $privateKeyString, - $cryptKey->getKeyContents() - ); - } - - public function test_can_use_crypto_keys_from_local_disk() - { - Passport::loadKeysFrom(__DIR__.'/../keys'); - - $privateKey = openssl_pkey_new(); - - openssl_pkey_export_to_file($privateKey, __DIR__.'/../keys/oauth-private.key'); - openssl_pkey_export($privateKey, $privateKeyString); - chmod(__DIR__.'/../keys/oauth-private.key', 0600); - - $config = m::mock(Config::class, function ($config) { - $config->shouldReceive('get')->with('passport.private_key')->andReturn(null); - }); - - $provider = new PassportServiceProvider( - m::mock(App::class, ['make' => $config]) - ); - - // Call protected makeCryptKey method - $cryptKey = (function () { - return $this->makeCryptKey('private'); - })->call($provider); - - $this->assertSame( - $privateKeyString, - file_get_contents($cryptKey->getKeyPath()) - ); - } -} diff --git a/tests/Unit/PassportTest.php b/tests/Unit/PassportTest.php index 615be3331..0056692ad 100644 --- a/tests/Unit/PassportTest.php +++ b/tests/Unit/PassportTest.php @@ -67,6 +67,6 @@ public function test_refresh_token_model_can_be_changed() } } -class RefreshTokenStub +class RefreshTokenStub extends RefreshToken { } diff --git a/tests/Unit/TokenGuardTest.php b/tests/Unit/TokenGuardTest.php index d68bbed45..b6ecd8e64 100644 --- a/tests/Unit/TokenGuardTest.php +++ b/tests/Unit/TokenGuardTest.php @@ -14,7 +14,6 @@ use Laravel\Passport\Client; use Laravel\Passport\ClientRepository; use Laravel\Passport\Guards\TokenGuard; -use Laravel\Passport\HasApiTokens; use Laravel\Passport\Passport; use Laravel\Passport\PassportUserProvider; use League\OAuth2\Server\Exception\OAuthServerException; @@ -23,6 +22,7 @@ use Mockery as m; use PHPUnit\Framework\TestCase; use Psr\Http\Message\ServerRequestInterface; +use Workbench\App\Models\User as TokenGuardTestUser; class TokenGuardTest extends TestCase { @@ -553,11 +553,6 @@ public function test_clients_may_be_retrieved_from_cookies() } } -class TokenGuardTestUser -{ - use HasApiTokens; -} - class TokenGuardTestClient extends Client { public $provider;