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 all 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
9 changes: 4 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [8.2, 8.3]
php: [8.2, 8.3, 8.4]
laravel: [11]

name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
Expand All @@ -29,15 +29,14 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
extensions: dom, curl, libxml, mbstring, zip
ini-values: error_reporting=E_ALL
tools: composer:v2
coverage: none

- name: Install dependencies
run: |
composer require "illuminate/contracts=^${{ matrix.laravel }}" --no-update
composer update --prefer-dist --no-interaction --no-progress
composer update --prefer-dist --no-interaction --no-progress --with="illuminate/contracts=^${{ matrix.laravel }}"

- name: Execute tests
run: vendor/bin/phpunit
run: vendor/bin/phpunit --fail-on-deprecation --fail-on-notice --fail-on-risky --fail-on-warning
4 changes: 2 additions & 2 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ PHP 8.2 is now the minimum required version.

### Minimum Laravel Version

PR: https://github.com/laravel/passport/pull/1757, https://github.com/laravel/passport/pull/1783
PR: https://github.com/laravel/passport/pull/1757, https://github.com/laravel/passport/pull/1783, https://github.com/laravel/passport/pull/1797

Laravel 11.14 is now the minimum required version.
Laravel 11.35 is now the minimum required version.

### OAuth2 Server

Expand Down
39 changes: 21 additions & 18 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,27 @@
"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",
"lcobucci/jwt": "^5.0",
"league/oauth2-server": "^9.0",
"nyholm/psr7": "^1.5",
"illuminate/auth": "^11.35",
"illuminate/console": "^11.35",
"illuminate/container": "^11.35",
"illuminate/contracts": "^11.35",
"illuminate/cookie": "^11.35",
"illuminate/database": "^11.35",
"illuminate/encryption": "^11.35",
"illuminate/http": "^11.35",
"illuminate/support": "^11.35",
"league/oauth2-server": "^9.1",
"php-http/discovery": "^1.20",
"phpseclib/phpseclib": "^3.0",
"symfony/console": "^7.0",
"psr/http-factory-implementation": "*",
"symfony/console": "^7.1",
"symfony/psr-http-message-bridge": "^7.1"
},
"require-dev": {
"mockery/mockery": "^1.0",
"orchestra/testbench": "^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.5|^11.0"
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.6",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^11.4"
},
"autoload": {
"psr-4": {
Expand All @@ -61,7 +61,10 @@
}
},
"config": {
"sort-packages": true
"sort-packages": true,
"allow-plugins": {
"php-http/discovery": false
}
},
"scripts": {
"post-autoload-dump": "@prepare",
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
15 changes: 7 additions & 8 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 All @@ -60,7 +59,7 @@ public static function fromPsrRequest(ServerRequestInterface $request): static
*/
public function can(string $scope): bool
{
return in_array('*', $this->oauth_scopes) || $this->scopeExists($scope, $this->oauth_scopes);
return in_array('*', $this->oauth_scopes) || $this->scopeExistsIn($scope, $this->oauth_scopes);
}

/**
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
13 changes: 7 additions & 6 deletions src/ApiTokenCookieFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace Laravel\Passport;

use Carbon\Carbon;
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 +26,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'])->getTimestamp();

return new Cookie(
Passport::cookie(),
Expand All @@ -37,19 +37,20 @@ public function make(string|int $userId, string $csrfToken): Cookie
$config['secure'],
true,
false,
$config['same_site'] ?? null
$config['same_site'] ?? null,
$config['partitioned'] ?? false
);
}

/**
* 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, int $expiration): string
{
return JWT::encode([
'sub' => $userId,
'csrf' => $csrfToken,
'expiry' => $expiration->getTimestamp(),
'jti' => $csrfToken,
'exp' => $expiration,
], Passport::tokenEncryptionKey($this->encrypter), 'HS256');
}
}
11 changes: 3 additions & 8 deletions src/Bridge/AccessTokenRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Laravel\Passport\Bridge;

use DateTime;
use Illuminate\Contracts\Events\Dispatcher;
use Laravel\Passport\Events\AccessTokenCreated;
use Laravel\Passport\Events\AccessTokenRevoked;
Expand All @@ -13,8 +12,6 @@

class AccessTokenRepository implements AccessTokenRepositoryInterface
{
use FormatsScopesForStorage;

/**
* Create a new repository instance.
*/
Expand All @@ -39,16 +36,14 @@ public function getNewToken(
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void
{
Passport::token()->newQuery()->create([
Passport::token()->forceFill([
'id' => $id = $accessTokenEntity->getIdentifier(),
'user_id' => $userId = $accessTokenEntity->getUserIdentifier(),
'client_id' => $clientId = $accessTokenEntity->getClient()->getIdentifier(),
'scopes' => $this->scopesToArray($accessTokenEntity->getScopes()),
'scopes' => $accessTokenEntity->getScopes(),
'revoked' => false,
'created_at' => new DateTime,
'updated_at' => new DateTime,
'expires_at' => $accessTokenEntity->getExpiryDateTime(),
]);
])->save();

$this->events->dispatch(new AccessTokenCreated($id, $userId, $clientId));
}
Expand Down
4 changes: 1 addition & 3 deletions src/Bridge/AuthCodeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

class AuthCodeRepository implements AuthCodeRepositoryInterface
{
use FormatsScopesForStorage;

/**
* {@inheritdoc}
*/
Expand All @@ -27,7 +25,7 @@ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): voi
'id' => $authCodeEntity->getIdentifier(),
'user_id' => $authCodeEntity->getUserIdentifier(),
'client_id' => $authCodeEntity->getClient()->getIdentifier(),
'scopes' => $this->formatScopesForStorage($authCodeEntity->getScopes()),
'scopes' => json_encode($authCodeEntity->getScopes()),
'revoked' => false,
'expires_at' => $authCodeEntity->getExpiryDateTime(),
])->save();
Expand Down
3 changes: 2 additions & 1 deletion src/Bridge/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ public function __construct(
string $name,
array $redirectUri,
bool $isConfidential = false,
public ?string $provider = null
public ?string $provider = null,
public array $grantTypes = []
) {
$this->setIdentifier($identifier);

Expand Down
3 changes: 2 additions & 1 deletion src/Bridge/ClientRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ protected function fromClientModel(ClientModel $model): ClientEntityInterface
$model->name,
$model->redirect_uris,
$model->confidential(),
$model->provider
$model->provider,
$model->grant_types
);
}
}
29 changes: 0 additions & 29 deletions src/Bridge/FormatsScopesForStorage.php

This file was deleted.

19 changes: 19 additions & 0 deletions src/Bridge/PersonalAccessBearerTokenResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Laravel\Passport\Bridge;

use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;

class PersonalAccessBearerTokenResponse extends BearerTokenResponse
{
/**
* {@inheritdoc}
*/
protected function getExtraParams(AccessTokenEntityInterface $accessToken): array
{
return [
'access_token_id' => $accessToken->getIdentifier(),
];
}
}
11 changes: 11 additions & 0 deletions src/Bridge/PersonalAccessGrant.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
namespace Laravel\Passport\Bridge;

use DateInterval;
use Laravel\Passport\Passport;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\Grant\AbstractGrant;
use League\OAuth2\Server\RequestAccessTokenEvent;
use League\OAuth2\Server\RequestEvent;
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
use Psr\Http\Message\ServerRequestInterface;

Expand Down Expand Up @@ -47,6 +50,14 @@ public function respondToAccessTokenRequest(
$scopes
);

// Send event to emitter
$this->getEmitter()->emit(new RequestAccessTokenEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request, $accessToken));

// Persist access token's name
Passport::token()->newQuery()->whereKey($accessToken->getIdentifier())->update([
'name' => $this->getRequestParameter('name', $request),
]);

// Inject access token into response type
$responseType->setAccessToken($accessToken);

Expand Down
4 changes: 2 additions & 2 deletions src/Bridge/RefreshTokenRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public function getNewRefreshToken(): ?RefreshTokenEntityInterface
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void
{
Passport::refreshToken()->newQuery()->create([
Passport::refreshToken()->forceFill([
'id' => $id = $refreshTokenEntity->getIdentifier(),
'access_token_id' => $accessTokenId = $refreshTokenEntity->getAccessToken()->getIdentifier(),
'revoked' => false,
'expires_at' => $refreshTokenEntity->getExpiryDateTime(),
]);
])->save();

$this->events->dispatch(new RefreshTokenCreated($id, $accessTokenId));
}
Expand Down
Loading
Loading