Skip to content

Commit

Permalink
Merge branch 'master' into patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
hafezdivandari committed Oct 23, 2024
2 parents 92fb400 + 1dc1ee8 commit b04eea5
Show file tree
Hide file tree
Showing 32 changed files with 565 additions and 181 deletions.
34 changes: 33 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [9.0.1] - released 2024-10-14
### Fixed
- Auto-generated event emitter is now persisted. Previously, a new emitter was generated every time (PR #1428)
- Fixed bug where you could not omit a redirect uri even if one had not been specified during the auth request (PR #1428)
- Fixed bug where "state" parameter wasn't present on `invalid_scope` error response and wasn't on fragment part of `access_denied` redirect URI on Implicit grant (PR #1298)
- Fixed bug where disabling refresh token revocation via `revokeRefreshTokens(false)` unintentionally disables issuing new refresh token (PR #1449)

## [9.0.0] - released 2024-05-13
### Added
- Device Authorization Grant added (PR #1074)
- GrantTypeInterface has a new function, `revokeRefreshTokens()` for enabling or disabling refresh tokens after use (PR #1375)
- A CryptKeyInterface to allow developers to change the CryptKey implementation with greater ease (PR #1044)
- The authorization server can now finalize scopes when a client uses a refresh token (PR #1094)
- An AuthorizationRequestInterface to make it easier to extend the AuthorizationRequest (PR #1110)
- Added function `getKeyContents()` to the `CryptKeyInterface` (PR #1375)

### Fixed
- Basic authorization is now case insensitive (PR #1403)
- If a refresh token has expired, been revoked, cannot be decrypted, or does not belong to the correct client, the server will now issue an `invalid_grant` error and a HTTP 400 response. In previous versions the server incorrectly issued an `invalid_request` and HTTP 401 response (PR #1042) (PR #1082)

### Changed
- All interfaces now specify types for all params and return values. Strict typing enforced (PR #1074)
- Request parameters are now parsed into strings to use internally in the library (PR #1402)
- Authorization Request objects are now created through the factory method, `createAuthorizationRequest()` (PR #1111)
- Changed parameters for `finalizeScopes()` to allow a reference to an auth code ID (PR #1112)
- AccessTokenEntityInterface now requires the implementation of `toString()` instead of the magic method `__toString()` (PR #1395)

### Removed
- Removed message property from OAuthException HTTP response. Now just use error_description as per the OAuth 2 spec (PR #1375)

## [9.0.0-RC1] - released 2024-03-27
### Added
- Device Authorization Grant added (PR #1074)
Expand Down Expand Up @@ -625,7 +655,9 @@ Version 5 is a complete code rewrite.

- First major release

[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/9.0.0-RC1...HEAD
[Unreleased]: https://github.com/thephpleague/oauth2-server/compare/9.0.1...HEAD
[9.0.1]: https://github.com/thephpleague/oauth2-server/compare/9.0.0...9.0.1
[9.0.0]: https://github.com/thephpleague/oauth2-server/compare/9.0.0-RC1...9.0.0
[9.0.0-RC1]: https://github.com/thephpleague/oauth2-server/compare/8.5.4...9.0.0-RC1
[8.5.4]: https://github.com/thephpleague/oauth2-server/compare/8.5.3...8.5.4
[8.5.3]: https://github.com/thephpleague/oauth2-server/compare/8.5.2...8.5.3
Expand Down
4 changes: 2 additions & 2 deletions examples/src/Entities/UserEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class UserEntity implements UserEntityInterface
/**
* Return the user's identifier.
*/
public function getIdentifier(): mixed
public function getIdentifier(): string
{
return 1;
return '1';
}
}
2 changes: 2 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<file>tests</file>
<file>examples</file>

<exclude-pattern>examples/vendor/*</exclude-pattern>

<rule ref="PSR12">
<exclude name="Generic.Files.LineLength.TooLong" />
</rule>
Expand Down
6 changes: 1 addition & 5 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@ parameters:
level: 8
paths:
- src
- tests
ignoreErrors:
-
message: '#Call to an undefined method League\\OAuth2\\Server\\ResponseTypes\\ResponseTypeInterface::getAccessToken\(\)\.#'
path: tests/Grant/ClientCredentialsGrantTest.php
- tests
5 changes: 2 additions & 3 deletions src/CryptKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function sprintf;
use function strpos;
use function trigger_error;

class CryptKey implements CryptKeyInterface
Expand All @@ -43,13 +42,13 @@ class CryptKey implements CryptKeyInterface

public function __construct(string $keyPath, protected ?string $passPhrase = null, bool $keyPermissionsCheck = true)
{
if (strpos($keyPath, self::FILE_PREFIX) !== 0 && $this->isValidKey($keyPath, $this->passPhrase ?? '')) {
if (str_starts_with($keyPath, self::FILE_PREFIX) === false && $this->isValidKey($keyPath, $this->passPhrase ?? '')) {
$this->keyContents = $keyPath;
$this->keyPath = '';
// There's no file, so no need for permission check.
$keyPermissionsCheck = false;
} elseif (is_file($keyPath)) {
if (strpos($keyPath, self::FILE_PREFIX) !== 0) {
if (str_starts_with($keyPath, self::FILE_PREFIX) === false) {
$keyPath = self::FILE_PREFIX . $keyPath;
}

Expand Down
6 changes: 5 additions & 1 deletion src/Entities/RefreshTokenEntityInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ interface RefreshTokenEntityInterface
{
/**
* Get the token's identifier.
*
* @return non-empty-string
*/
public function getIdentifier(): string;

/**
* Set the token's identifier.
*
* @param non-empty-string $identifier
*/
public function setIdentifier(mixed $identifier): void;
public function setIdentifier(string $identifier): void;

/**
* Get the token's expiry date time.
Expand Down
2 changes: 2 additions & 0 deletions src/Entities/ScopeEntityInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ interface ScopeEntityInterface extends JsonSerializable
{
/**
* Get the scope's identifier.
*
* @return non-empty-string
*/
public function getIdentifier(): string;
}
10 changes: 8 additions & 2 deletions src/Entities/TokenInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ interface TokenInterface
{
/**
* Get the token's identifier.
*
* @return non-empty-string
*/
public function getIdentifier(): string;

/**
* Set the token's identifier.
*
* @param non-empty-string $identifier
*/
public function setIdentifier(mixed $identifier): void;
public function setIdentifier(string $identifier): void;

/**
* Get the token's expiry date time.
Expand All @@ -45,8 +49,10 @@ public function setUserIdentifier(string $identifier): void;

/**
* Get the token user's identifier.
*
* @return non-empty-string|null
*/
public function getUserIdentifier(): string|int|null;
public function getUserIdentifier(): string|null;

/**
* Get the client that the token was issued to.
Expand Down
3 changes: 3 additions & 0 deletions src/Entities/Traits/DeviceCodeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ abstract public function getExpiryDateTime(): DateTimeImmutable;
*/
abstract public function getScopes(): array;

/**
* @return non-empty-string
*/
abstract public function getIdentifier(): string;

public function getLastPolledAt(): ?DateTimeImmutable
Expand Down
5 changes: 4 additions & 1 deletion src/Entities/Traits/EntityTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ public function getIdentifier(): string
return $this->identifier;
}

public function setIdentifier(mixed $identifier): void
/**
* @param non-empty-string $identifier
*/
public function setIdentifier(string $identifier): void
{
$this->identifier = $identifier;
}
Expand Down
4 changes: 3 additions & 1 deletion src/Entities/UserEntityInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ interface UserEntityInterface
{
/**
* Return the user's identifier.
*
* @return non-empty-string
*/
public function getIdentifier(): mixed;
public function getIdentifier(): string;
}
2 changes: 1 addition & 1 deletion src/EventEmitting/EmitterAwarePolyfill.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ trait EmitterAwarePolyfill

public function getEmitter(): EventEmitter
{
return $this->emitter ?? new EventEmitter();
return $this->emitter ??= new EventEmitter();
}

public function setEmitter(EventEmitter $emitter): self
Expand Down
8 changes: 3 additions & 5 deletions src/Exception/OAuthServerException.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
use function htmlspecialchars;
use function http_build_query;
use function sprintf;
use function strpos;
use function strstr;

class OAuthServerException extends Exception
{
Expand Down Expand Up @@ -269,9 +267,9 @@ public function generateHttpResponse(ResponseInterface $response, bool $useFragm

if ($this->redirectUri !== null) {
if ($useFragment === true) {
$this->redirectUri .= (strstr($this->redirectUri, '#') === false) ? '#' : '&';
$this->redirectUri .= (str_contains($this->redirectUri, '#') === false) ? '#' : '&';
} else {
$this->redirectUri .= (strstr($this->redirectUri, '?') === false) ? '?' : '&';
$this->redirectUri .= (str_contains($this->redirectUri, '?') === false) ? '?' : '&';
}

return $response->withStatus(302)->withHeader('Location', $this->redirectUri . http_build_query($payload));
Expand Down Expand Up @@ -310,7 +308,7 @@ public function getHttpHeaders(): array
// include the "WWW-Authenticate" response header field
// matching the authentication scheme used by the client.
if ($this->errorType === 'invalid_client' && $this->requestHasAuthorizationHeader()) {
$authScheme = strpos($this->serverRequest->getHeader('Authorization')[0], 'Bearer') === 0 ? 'Bearer' : 'Basic';
$authScheme = str_starts_with($this->serverRequest->getHeader('Authorization')[0], 'Bearer') ? 'Bearer' : 'Basic';

$headers['WWW-Authenticate'] = $authScheme . ' realm="OAuth"';
}
Expand Down
16 changes: 13 additions & 3 deletions src/Grant/AbstractAuthorizeGrant.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@

namespace League\OAuth2\Server\Grant;

use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use League\OAuth2\Server\RequestTypes\AuthorizationRequestInterface;

use function http_build_query;
use function strstr;

abstract class AbstractAuthorizeGrant extends AbstractGrant
{
/**
* @param mixed[] $params
* @param array<array-key,mixed> $params
*/
public function makeRedirectUri(string $uri, array $params = [], string $queryDelimiter = '?'): string
{
$uri .= (strstr($uri, $queryDelimiter) === false) ? $queryDelimiter : '&';
$uri .= str_contains($uri, $queryDelimiter) ? '&' : $queryDelimiter;

return $uri . http_build_query($params);
}
Expand All @@ -36,4 +36,14 @@ protected function createAuthorizationRequest(): AuthorizationRequestInterface
{
return new AuthorizationRequest();
}

/**
* Get the client redirect URI.
*/
protected function getClientRedirectUri(ClientEntityInterface $client): string
{
return is_array($client->getRedirectUri())
? $client->getRedirectUri()[0]
: $client->getRedirectUri();
}
}
Loading

0 comments on commit b04eea5

Please sign in to comment.