Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[13.x] Release Passport 13.x #1797

Draft
wants to merge 29 commits into
base: 13.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b63a429
fix some types
hafezdivandari Oct 13, 2024
6067321
switch to uuid v7
hafezdivandari Oct 13, 2024
9ed8646
fix types
hafezdivandari Oct 13, 2024
e254441
improve tests
hafezdivandari Oct 13, 2024
1d12f5f
formatting
hafezdivandari Oct 15, 2024
6c0837c
add more tests
hafezdivandari Oct 15, 2024
32b8e8f
add more tests
hafezdivandari Oct 15, 2024
91cc26a
formatting
hafezdivandari Oct 17, 2024
2567f7b
formatting
hafezdivandari Oct 17, 2024
a9a3916
fix some types
hafezdivandari Oct 17, 2024
dfbdaa0
require Laravel 11.7 for uuid v7
hafezdivandari Oct 17, 2024
74b48a2
add more tests
hafezdivandari Oct 19, 2024
b8bfc87
enhance issuing PATs
hafezdivandari Oct 26, 2024
0c79897
add support for PHP 8.4
hafezdivandari Oct 28, 2024
6e0686e
formatting
hafezdivandari Oct 29, 2024
72451d2
remove unused trait
hafezdivandari Oct 30, 2024
b4c1bba
formatting
hafezdivandari Oct 31, 2024
fece76e
add guard name to authentication exception
hafezdivandari Nov 6, 2024
c059b92
formatting
hafezdivandari Nov 17, 2024
1e99e8e
add client grant_types attribute
hafezdivandari Nov 19, 2024
7b597d4
remove lcobucci/jwt
hafezdivandari Nov 22, 2024
ca016b9
fix cookie jwt
hafezdivandari Nov 23, 2024
d7f42dd
fix tests with notices
hafezdivandari Nov 23, 2024
8131d9e
make tests more strict
hafezdivandari Nov 24, 2024
67fde5f
bump dependencies
hafezdivandari Nov 24, 2024
1e79f26
wip
hafezdivandari Dec 10, 2024
46e0591
better naming
hafezdivandari Dec 11, 2024
ebf4318
formatting
hafezdivandari Dec 11, 2024
cc4c874
enable psr auto-discovery
hafezdivandari Dec 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
"ext-json": "*",
"ext-openssl": "*",
"firebase/php-jwt": "^6.4",
"illuminate/auth": "^11.14",
"illuminate/console": "^11.14",
"illuminate/container": "^11.14",
"illuminate/contracts": "^11.14",
"illuminate/cookie": "^11.14",
"illuminate/database": "^11.14",
"illuminate/encryption": "^11.14",
"illuminate/http": "^11.14",
"illuminate/support": "^11.14",
"illuminate/auth": "^11.17",
"illuminate/console": "^11.17",
"illuminate/container": "^11.17",
"illuminate/contracts": "^11.17",
"illuminate/cookie": "^11.17",
"illuminate/database": "^11.17",
"illuminate/encryption": "^11.17",
"illuminate/http": "^11.17",
"illuminate/support": "^11.17",
"lcobucci/jwt": "^5.0",
"league/oauth2-server": "^9.0",
"nyholm/psr7": "^1.5",
Expand Down
2 changes: 1 addition & 1 deletion routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

$guard = config('passport.guard', null);

Route::middleware(['web', $guard ? 'auth:'.$guard : 'auth'])->group(function () {
Route::middleware(['web', $guard ? 'auth:'.$guard : 'auth'])->group(function (): void {
Route::post('/token/refresh', [
'uses' => 'TransientTokenController@refresh',
'as' => 'token.refresh',
Expand Down
13 changes: 6 additions & 7 deletions src/AccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
use Psr\Http\Message\ServerRequestInterface;

/**
* @template TKey of string
* @template TValue
*
* @implements \Illuminate\Contracts\Support\Arrayable<TKey, TValue>
* @implements \Illuminate\Contracts\Support\Arrayable<string, TValue>
*
* @property string $oauth_access_token_id
* @property string $oauth_client_id
Expand All @@ -26,19 +25,19 @@ class AccessToken implements Arrayable, Jsonable, JsonSerializable
/**
* The token instance.
*/
protected ?Token $token;
protected ?Token $token = null;

/**
* All the attributes set on the access token instance.
*
* @var array<TKey, TValue>
* @var array<string, TValue>
*/
protected array $attributes = [];

/**
* Create a new access token instance.
*
* @param array<TKey, TValue> $attributes
* @param array<string, TValue> $attributes
*/
public function __construct(array $attributes = [])
{
Expand Down Expand Up @@ -98,7 +97,7 @@ protected function getToken(): ?Token
/**
* Convert the access token instance to an array.
*
* @return array<TKey, TValue>
* @return array<string, TValue>
*/
public function toArray(): array
{
Expand All @@ -108,7 +107,7 @@ public function toArray(): array
/**
* Convert the object into something JSON serializable.
*
* @return array<TKey, TValue>
* @return array<string, TValue>
*/
public function jsonSerialize(): array
{
Expand Down
7 changes: 4 additions & 3 deletions src/ApiTokenCookieFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

namespace Laravel\Passport;

use Carbon\Carbon;
use DateTime;
use Firebase\JWT\JWT;
use Illuminate\Contracts\Config\Repository as Config;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Support\Facades\Date;
use Symfony\Component\HttpFoundation\Cookie;

class ApiTokenCookieFactory
Expand All @@ -26,7 +27,7 @@ public function make(string|int $userId, string $csrfToken): Cookie
{
$config = $this->config->get('session');

$expiration = Carbon::now()->addMinutes((int) $config['lifetime']);
$expiration = Date::now()->addMinutes((int) $config['lifetime']);

return new Cookie(
Passport::cookie(),
Expand All @@ -44,7 +45,7 @@ public function make(string|int $userId, string $csrfToken): Cookie
/**
* Create a new JWT token for the given user ID and CSRF token.
*/
protected function createToken(string|int $userId, string $csrfToken, Carbon $expiration): string
protected function createToken(string|int $userId, string $csrfToken, DateTime $expiration): string
{
return JWT::encode([
'sub' => $userId,
Expand Down
2 changes: 1 addition & 1 deletion src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public function uniqueIds(): array
*/
public function newUniqueId(): ?string
{
return $this->usesUniqueIds ? (string) Str::orderedUuid() : null;
return $this->usesUniqueIds ? (string) Str::uuid7() : null;
hafezdivandari marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/ClientRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ public function personalAccessClient(string $provider): Client
->newQuery()
->where('revoked', false)
->whereNull('user_id')
->where(function (Builder $query) use ($provider) {
$query->when($provider === config('auth.guards.api.provider'), function (Builder $query) {
->where(function (Builder $query) use ($provider): void {
$query->when($provider === config('auth.guards.api.provider'), function (Builder $query): void {
$query->orWhereNull('provider');
})->orWhere('provider', $provider);
})
->latest()
->get()
->first(fn (Client $client) => $client->hasGrantType('personal_access'))
->first(fn (Client $client): bool => $client->hasGrantType('personal_access'))
?? throw new RuntimeException(
"Personal access client not found for '$provider' user provider. Please create one."
);
Expand Down
16 changes: 8 additions & 8 deletions src/Console/ClientCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ class ClientCommand extends Command
*/
public function handle(ClientRepository $clients): void
{
if (! $this->hasOption('name')) {
$this->input->setOption('name', $this->ask(
if (! $this->option('name')) {
$this->input->setOption('name', $this->components->ask(
'What should we name the client?',
config('app.name')
));
Expand Down Expand Up @@ -69,7 +69,7 @@ public function handle(ClientRepository $clients): void
*/
protected function createPersonalAccessClient(ClientRepository $clients): ?Client
{
$provider = $this->option('provider') ?: $this->choice(
$provider = $this->option('provider') ?: $this->components->choice(
'Which user provider should this client use to retrieve users?',
collect(config('auth.guards'))->where('driver', 'passport')->pluck('provider')->all(),
config('auth.guards.api.provider')
Expand All @@ -85,15 +85,15 @@ protected function createPersonalAccessClient(ClientRepository $clients): ?Clien
*/
protected function createPasswordClient(ClientRepository $clients): Client
{
$provider = $this->option('provider') ?: $this->choice(
$provider = $this->option('provider') ?: $this->components->choice(
'Which user provider should this client use to retrieve users?',
collect(config('auth.guards'))->where('driver', 'passport')->pluck('provider')->all(),
config('auth.guards.api.provider')
);

$confidential = $this->hasOption('public')
? ! $this->option('public')
: $this->confirm('Would you like to make this client confidential?');
: $this->components->confirm('Would you like to make this client confidential?');

return $clients->createPasswordGrantClient($this->option('name'), $provider, $confidential);
}
Expand All @@ -111,7 +111,7 @@ protected function createClientCredentialsClient(ClientRepository $clients): Cli
*/
protected function createImplicitClient(ClientRepository $clients): Client
{
$redirect = $this->option('redirect_uri') ?: $this->ask(
$redirect = $this->option('redirect_uri') ?: $this->components->ask(
'Where should we redirect the request after authorization?',
url('/auth/callback')
);
Expand All @@ -124,14 +124,14 @@ protected function createImplicitClient(ClientRepository $clients): Client
*/
protected function createAuthCodeClient(ClientRepository $clients): Client
{
$redirect = $this->option('redirect_uri') ?: $this->ask(
$redirect = $this->option('redirect_uri') ?: $this->components->ask(
'Where should we redirect the request after authorization?',
url('/auth/callback')
);

$confidential = $this->hasOption('public')
? ! $this->option('public')
: $this->confirm('Would you like to make this client confidential?', true);
: $this->components->confirm('Would you like to make this client confidential?', true);

return $clients->createAuthorizationCodeGrantClient(
$this->option('name'), explode(',', $redirect), $confidential,
Expand Down
2 changes: 1 addition & 1 deletion src/Console/HashCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class HashCommand extends Command
public function handle(): void
{
if ($this->option('force') ||
$this->confirm('Are you sure you want to hash all client secrets? This cannot be undone.')) {
$this->components->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;
Expand Down
4 changes: 2 additions & 2 deletions src/Console/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public function handle(): void
$this->call('vendor:publish', ['--tag' => 'passport-config']);
$this->call('vendor:publish', ['--tag' => 'passport-migrations']);

if ($this->confirm('Would you like to run all pending database migrations?', true)) {
if ($this->components->confirm('Would you like to run all pending database migrations?', true)) {
$this->call('migrate');

if ($this->confirm('Would you like to create the "personal access" grant client?', true)) {
if ($this->components->confirm('Would you like to create the "personal access" grant client?', true)) {
$this->call('passport:client', [
'--personal' => true,
'--name' => config('app.name'),
Expand Down
6 changes: 3 additions & 3 deletions src/Console/PurgeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Date;
use Laravel\Passport\Passport;
use Symfony\Component\Console\Attribute\AsCommand;

Expand Down Expand Up @@ -36,10 +36,10 @@ public function handle(): void
$revoked = $this->option('revoked') || ! $this->option('expired');

$expired = $this->option('expired') || ! $this->option('revoked')
? Carbon::now()->subHours($this->option('hours'))
? Date::now()->subHours($this->option('hours'))
: false;

$constraint = fn (Builder $query) => $query
$constraint = fn (Builder $query): Builder => $query
->when($revoked, fn () => $query->orWhere('revoked', true))
->when($expired, fn () => $query->orWhere('expires_at', '<', $expired));

Expand Down
8 changes: 4 additions & 4 deletions src/HasApiTokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public function clients(): HasMany
public function tokens(): HasMany
{
return $this->hasMany(Passport::tokenModel(), 'user_id')
->where(function (Builder $query) {
$query->whereHas('client', function (Builder $query) {
$query->where(function (Builder $query) {
->where(function (Builder $query): void {
$query->whereHas('client', function (Builder $query): void {
$query->where(function (Builder $query): void {
$provider = $this->getProvider();

$query->when($provider === config('auth.guards.api.provider'), function (Builder $query) {
$query->when($provider === config('auth.guards.api.provider'), function (Builder $query): void {
$query->orWhereNull('provider');
})->orWhere('provider', $provider);
});
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Controllers/AuthorizationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function authorize(
AuthorizationViewResponse $viewResponse
): Response|AuthorizationViewResponse {
$authRequest = $this->withErrorHandling(
fn () => $this->server->validateAuthorizationRequest($psrRequest),
fn (): AuthorizationRequestInterface => $this->server->validateAuthorizationRequest($psrRequest),
($psrRequest->getQueryParams()['response_type'] ?? null) === 'token'
);

Expand Down
24 changes: 12 additions & 12 deletions src/Passport.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace Laravel\Passport;

use Carbon\Carbon;
use Closure;
use DateInterval;
use DateTimeInterface;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Date;
use Laravel\Passport\Contracts\AuthorizationViewResponse;
use Laravel\Passport\Http\Responses\SimpleViewResponse;
use League\OAuth2\Server\ResourceServer;
Expand Down Expand Up @@ -49,17 +49,17 @@ class Passport
/**
* The interval when access tokens expire.
*/
public static ?DateInterval $tokensExpireIn;
public static ?DateInterval $tokensExpireIn = null;

/**
* The date when refresh tokens expire.
*/
public static ?DateInterval $refreshTokensExpireIn;
public static ?DateInterval $refreshTokensExpireIn = null;

/**
* The date when personal access tokens expire.
*/
public static ?DateInterval $personalAccessTokensExpireIn;
public static ?DateInterval $personalAccessTokensExpireIn = null;

/**
* The name for API token cookies.
Expand Down Expand Up @@ -272,7 +272,7 @@ public static function tokensExpireIn(DateTimeInterface|DateInterval|null $date
}

return static::$tokensExpireIn = $date instanceof DateTimeInterface
? Carbon::now()->diff($date)
? Date::now()->diff($date)
: $date;
}

Expand All @@ -286,7 +286,7 @@ public static function refreshTokensExpireIn(DateTimeInterface|DateInterval|null
}

return static::$refreshTokensExpireIn = $date instanceof DateTimeInterface
? Carbon::now()->diff($date)
? Date::now()->diff($date)
: $date;
}

Expand All @@ -300,7 +300,7 @@ public static function personalAccessTokensExpireIn(DateTimeInterface|DateInterv
}

return static::$personalAccessTokensExpireIn = $date instanceof DateTimeInterface
? Carbon::now()->diff($date)
? Date::now()->diff($date)
: $date;
}

Expand Down Expand Up @@ -361,11 +361,11 @@ public static function actingAs($user, array $scopes = [], ?string $guard = 'api
public static function actingAsClient(Client $client, array $scopes = [], ?string $guard = 'api'): Client
{
$mock = Mockery::mock(ResourceServer::class);
$mock->shouldReceive('validateAuthenticatedRequest')
->andReturnUsing(function (ServerRequestInterface $request) use ($client, $scopes) {
return $request->withAttribute('oauth_client_id', $client->getKey())
->withAttribute('oauth_scopes', $scopes);
});
$mock->shouldReceive('validateAuthenticatedRequest')->andReturnUsing(
fn (ServerRequestInterface $request) => $request
->withAttribute('oauth_client_id', $client->getKey())
->withAttribute('oauth_scopes', $scopes)
);

app()->instance(ResourceServer::class, $mock);

Expand Down
Loading