Skip to content

Commit

Permalink
[13.x] Support OAuth2 Server v9 (#1734)
Browse files Browse the repository at this point in the history
* support OAuth2 Server 9

* formatting

* formatting

* drop php 8.0

* use fqn

* wip

* wip

* wip

* formatting

* formatting

* wip

* remove redundant attribute

* fix tests

* update upgrade guide

* force re-run tests

* wip

* wip

* add an entry on upgrade guide for oauth2 server

* Update UPGRADE.md

* Update UPGRADE.md

* Update UPGRADE.md

---------

Co-authored-by: Dries Vints <dries@vints.be>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
3 people authored May 17, 2024
1 parent 8ea1dd4 commit fc7e2da
Show file tree
Hide file tree
Showing 30 changed files with 173 additions and 223 deletions.
6 changes: 1 addition & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ jobs:
strategy:
fail-fast: true
matrix:
php: ['8.0', 8.1, 8.2, 8.3]
php: [8.1, 8.2, 8.3]
laravel: [9, 10, 11]
exclude:
- php: '8.0'
laravel: 10
- php: '8.0'
laravel: 11
- php: 8.1
laravel: 11
- php: 8.3
Expand Down
16 changes: 16 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

## General Notes

## Upgrading To 13.0 From 12.x

### Minimum PHP Version

PR: https://github.com/laravel/passport/pull/1734

PHP 8.1 is now the minimum required version.

### OAuth2 Server

PR: https://github.com/laravel/passport/pull/1734

The `league/oauth2-server` Composer package which is utilized internally by Passport has been updated to 9.0, which adds additional types to method signatures. To ensure your application is compatible, you should review this package's complete [changelog](https://github.com/thephpleague/oauth2-server/blob/master/CHANGELOG.md#900---released-2024-05-13).

## Upgrading To 12.0 From 11.x

### Migration Changes
Expand All @@ -14,6 +28,8 @@ php artisan vendor:publish --tag=passport-migrations

### Password Grant Type

PR: https://github.com/laravel/passport/pull/1715

The password grant type is disabled by default. You may enable it by calling the `enablePasswordGrant` method in the `boot` method of your application's `App\Providers\AppServiceProvider` class:

```php
Expand Down
15 changes: 8 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
}
],
"require": {
"php": "^8.0",
"php": "^8.1",
"ext-json": "*",
"ext-openssl": "*",
"firebase/php-jwt": "^6.4",
"illuminate/auth": "^9.21|^10.0|^11.0",
"illuminate/console": "^9.21|^10.0|^11.0",
Expand All @@ -26,18 +27,18 @@
"illuminate/encryption": "^9.21|^10.0|^11.0",
"illuminate/http": "^9.21|^10.0|^11.0",
"illuminate/support": "^9.21|^10.0|^11.0",
"lcobucci/jwt": "^4.3|^5.0",
"league/oauth2-server": "^8.5.3",
"lcobucci/jwt": "^5.0",
"league/oauth2-server": "^9.0",
"nyholm/psr7": "^1.5",
"phpseclib/phpseclib": "^2.0|^3.0",
"phpseclib/phpseclib": "^3.0",
"symfony/console": "^6.0|^7.0",
"symfony/psr-http-message-bridge": "^2.1|^6.0|^7.0"
"symfony/psr-http-message-bridge": "^6.0|^7.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"orchestra/testbench": "^7.35|^8.14|^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.3|^10.5"
"phpunit/phpunit": "^9.3|^10.5|^11.0"
},
"autoload": {
"psr-4": {
Expand Down Expand Up @@ -66,6 +67,6 @@
"post-autoload-dump": "@prepare",
"prepare": "@php vendor/bin/testbench package:discover --ansi"
},
"minimum-stability": "dev",
"minimum-stability": "stable",
"prefer-stable": true
}
12 changes: 7 additions & 5 deletions database/factories/ClientFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
use Laravel\Passport\Client;
use Laravel\Passport\Passport;

/**
Expand All @@ -13,11 +12,14 @@
class ClientFactory extends Factory
{
/**
* The name of the factory's corresponding model.
* Get the name of the model that is generated by the factory.
*
* @var string
* @return class-string<\Illuminate\Database\Eloquent\Model>
*/
protected $model = Client::class;
public function modelName()
{
return $this->model ?? Passport::clientModel();
}

/**
* Define the model's default state.
Expand Down Expand Up @@ -46,7 +48,7 @@ public function definition()
protected function ensurePrimaryKeyIsSet(array $data)
{
if (Passport::clientUuids()) {
$keyName = (new $this->model)->getKeyName();
$keyName = (new ($this->modelName()))->getKeyName();

$data[$keyName] = (string) Str::orderedUuid();
}
Expand Down
11 changes: 5 additions & 6 deletions src/Bridge/AccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ class AccessToken implements AccessTokenEntityInterface
/**
* Create a new token instance.
*
* @param string $userIdentifier
* @param array $scopes
* @param \League\OAuth2\Server\Entities\ClientEntityInterface $client
* @return void
* @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes
*/
public function __construct($userIdentifier, array $scopes, ClientEntityInterface $client)
public function __construct(string|null $userIdentifier, array $scopes, ClientEntityInterface $client)
{
$this->setUserIdentifier($userIdentifier);
if (! is_null($userIdentifier)) {
$this->setUserIdentifier($userIdentifier);
}

foreach ($scopes as $scope) {
$this->addScope($scope);
Expand Down
37 changes: 14 additions & 23 deletions src/Bridge/AccessTokenRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,16 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface

/**
* The token repository instance.
*
* @var \Laravel\Passport\TokenRepository
*/
protected $tokenRepository;
protected TokenRepository $tokenRepository;

/**
* The event dispatcher instance.
*
* @var \Illuminate\Contracts\Events\Dispatcher
*/
protected $events;
protected Dispatcher $events;

/**
* Create a new repository instance.
*
* @param \Laravel\Passport\TokenRepository $tokenRepository
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @return void
*/
public function __construct(TokenRepository $tokenRepository, Dispatcher $events)
{
Expand All @@ -45,46 +37,45 @@ public function __construct(TokenRepository $tokenRepository, Dispatcher $events
/**
* {@inheritdoc}
*/
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null)
{
public function getNewToken(
ClientEntityInterface $clientEntity,
array $scopes,
string|null $userIdentifier = null
): AccessTokenEntityInterface {
return new Passport::$accessTokenEntity($userIdentifier, $scopes, $clientEntity);
}

/**
* {@inheritdoc}
*/
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity)
public function persistNewAccessToken(AccessTokenEntityInterface $accessTokenEntity): void
{
$this->tokenRepository->create([
'id' => $accessTokenEntity->getIdentifier(),
'user_id' => $accessTokenEntity->getUserIdentifier(),
'client_id' => $accessTokenEntity->getClient()->getIdentifier(),
'id' => $id = $accessTokenEntity->getIdentifier(),
'user_id' => $userId = $accessTokenEntity->getUserIdentifier(),
'client_id' => $clientId = $accessTokenEntity->getClient()->getIdentifier(),
'scopes' => $this->scopesToArray($accessTokenEntity->getScopes()),
'revoked' => false,
'created_at' => new DateTime,
'updated_at' => new DateTime,
'expires_at' => $accessTokenEntity->getExpiryDateTime(),
]);

$this->events->dispatch(new AccessTokenCreated(
$accessTokenEntity->getIdentifier(),
$accessTokenEntity->getUserIdentifier(),
$accessTokenEntity->getClient()->getIdentifier()
));
$this->events->dispatch(new AccessTokenCreated($id, $userId, $clientId));
}

/**
* {@inheritdoc}
*/
public function revokeAccessToken($tokenId)
public function revokeAccessToken(string $tokenId): void
{
$this->tokenRepository->revokeAccessToken($tokenId);
}

/**
* {@inheritdoc}
*/
public function isAccessTokenRevoked($tokenId)
public function isAccessTokenRevoked(string $tokenId): bool
{
return $this->tokenRepository->isAccessTokenRevoked($tokenId);
}
Expand Down
8 changes: 4 additions & 4 deletions src/Bridge/AuthCodeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface
/**
* {@inheritdoc}
*/
public function getNewAuthCode()
public function getNewAuthCode(): AuthCodeEntityInterface
{
return new AuthCode;
}

/**
* {@inheritdoc}
*/
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): void
{
$attributes = [
'id' => $authCodeEntity->getIdentifier(),
Expand All @@ -38,15 +38,15 @@ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
/**
* {@inheritdoc}
*/
public function revokeAuthCode($codeId)
public function revokeAuthCode(string $codeId): void
{
Passport::authCode()->where('id', $codeId)->update(['revoked' => true]);
}

/**
* {@inheritdoc}
*/
public function isAuthCodeRevoked($codeId)
public function isAuthCodeRevoked(string $codeId): bool
{
return Passport::authCode()->where('id', $codeId)->where('revoked', 1)->exists();
}
Expand Down
53 changes: 11 additions & 42 deletions src/Bridge/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,32 @@

use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\Traits\ClientTrait;
use League\OAuth2\Server\Entities\Traits\EntityTrait;

class Client implements ClientEntityInterface
{
use ClientTrait;

/**
* The client identifier.
*
* @var string
*/
protected $identifier;
use ClientTrait, EntityTrait;

/**
* The client's provider.
*
* @var string
*/
public $provider;
public ?string $provider;

/**
* Create a new client instance.
*
* @param string $identifier
* @param string $name
* @param string $redirectUri
* @param bool $isConfidential
* @param string|null $provider
* @return void
*/
public function __construct($identifier, $name, $redirectUri, $isConfidential = false, $provider = null)
{
$this->setIdentifier((string) $identifier);
public function __construct(
string $identifier,
string $name,
string $redirectUri,
bool $isConfidential = false,
?string $provider = null
) {
$this->setIdentifier($identifier);

$this->name = $name;
$this->isConfidential = $isConfidential;
$this->redirectUri = explode(',', $redirectUri);
$this->provider = $provider;
}

/**
* Get the client's identifier.
*
* @return string
*/
public function getIdentifier()
{
return (string) $this->identifier;
}

/**
* Set the client's identifier.
*
* @param string $identifier
* @return void
*/
public function setIdentifier($identifier)
{
$this->identifier = $identifier;
}
}
Loading

0 comments on commit fc7e2da

Please sign in to comment.