From 77e48f311abb4a46e5e35e6ef3b057327f9c00ba Mon Sep 17 00:00:00 2001 From: Karsten Dambekalns Date: Tue, 10 Dec 2024 21:55:51 +0100 Subject: [PATCH 1/6] Update actions ci.yaml --- .github/workflows/ci.yaml | 12 ++++++------ .gitignore | 2 ++ composer.json | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index be07b55..208944a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ master ] + branches: [ main ] pull_request: - branches: [ master ] + branches: [ main ] jobs: tests: @@ -22,7 +22,6 @@ jobs: - ubuntu-latest php-version: - - "8.0" - "8.1" - "8.2" - "8.3" @@ -36,7 +35,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Override PHP ini values for JIT compiler if: matrix.compiler == 'jit' @@ -59,12 +58,13 @@ jobs: run: echo "COMPOSER_CACHE_DIR=~\AppData\Local\Composer" >> $GITHUB_ENV - name: Cache dependencies installed with composer - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ${{ env.COMPOSER_CACHE_DIR }} key: php${{ matrix.php-version }}-composer-${{ matrix.dependencies }}-${{ hashFiles('**/composer.json') }} restore-keys: | php${{ matrix.php-version }}-composer-${{ matrix.dependencies }}- + - name: Install lowest dependencies with composer if: matrix.dependencies == 'lowest' run: composer update --no-ansi --no-interaction --no-progress --prefer-lowest @@ -80,6 +80,6 @@ jobs: run: vendor/bin/phpunit --coverage-clover=coverage.xml - name: Send code coverage report to Codecov.io - uses: codecov/codecov-action@v1 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 85e7c1d..95e2f44 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /.idea/ +vendor +Packages diff --git a/composer.json b/composer.json index 8847395..40bec1c 100644 --- a/composer.json +++ b/composer.json @@ -63,5 +63,10 @@ "Neos.Flow-20201205172733", "Neos.Flow-20201207104500" ] + }, + "config": { + "allow-plugins": { + "neos/composer-plugin": true + } } } From 0269444a551f4c57204a141752ee6021f5b11077 Mon Sep 17 00:00:00 2001 From: Karsten Dambekalns Date: Tue, 10 Dec 2024 22:28:12 +0100 Subject: [PATCH 2/6] Raise PHP requirement This package now requires at least PHP 8.1 and introduces support for PHP 8.4 --- .github/workflows/ci.yaml | 1 + composer.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 208944a..b65470f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,6 +25,7 @@ jobs: - "8.1" - "8.2" - "8.3" + - "8.4" compiler: - default diff --git a/composer.json b/composer.json index 40bec1c..9730e9d 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ } ], "require": { - "php": "8.0.* || 8.1.* || 8.2.* || 8.3.*", + "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*", "neos/flow": "^7.3 || ^8.0 || ^9.0", "guzzlehttp/guzzle": "^6.0 || ^7.0", "flownative/oauth2-client": "^4.0.0", From 2204ca9b42c39519b51b94d2a7cb6596c667745e Mon Sep 17 00:00:00 2001 From: Karsten Dambekalns Date: Tue, 10 Dec 2024 22:44:10 +0100 Subject: [PATCH 3/6] Further tweak CI --- .gitignore | 1 + composer.json | 2 +- phpunit.xml.dist | 34 ++++++++++++++-------------------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 95e2f44..1a28732 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.idea/ vendor Packages +composer.lock diff --git a/composer.json b/composer.json index 9730e9d..1041f27 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "psr/http-server-middleware": "^1.0" }, "require-dev": { - "phpunit/phpunit": "~8.0", + "phpunit/phpunit": "^9.0", "phpunit/php-code-coverage": "*" }, "autoload": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 998b2ed..5d468ee 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,22 +1,16 @@ - - - - - - - - ./Tests/Unit/ - - - - - - ./Classes - - + + + + ./Classes + + + + + + + + ./Tests/Unit/ + + From a7a9d3a696b23870d5db5d37fa6f08c7273c4db9 Mon Sep 17 00:00:00 2001 From: Karsten Dambekalns Date: Tue, 10 Dec 2024 23:37:18 +0100 Subject: [PATCH 4/6] Code cleanup --- .github/workflows/ci.yaml | 11 --------- .../Authentication/OpenIdConnectProvider.php | 12 +++++----- Classes/Authentication/OpenIdConnectToken.php | 4 ++-- Classes/Authentication/TokenArguments.php | 24 +++++++------------ Classes/Command/OidcCommandController.php | 2 +- Classes/Http/SetJwtCookieMiddleware.php | 10 -------- Classes/IdentityToken.php | 5 ++-- Classes/OAuthClient.php | 6 ++--- Classes/OpenIdConnectClient.php | 6 ++--- composer.json | 2 +- 10 files changed, 28 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b65470f..34cf5fb 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -27,9 +27,6 @@ jobs: - "8.3" - "8.4" - compiler: - - default - dependencies: - lowest - highest @@ -38,10 +35,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Override PHP ini values for JIT compiler - if: matrix.compiler == 'jit' - run: echo "PHP_INI_VALUES=assert.exception=1, zend.assertions=1, opcache.enable=1, opcache.enable_cli=1, opcache.optimization_level=-1, opcache.jit=1205, opcache.jit_buffer_size=4096M" >> $GITHUB_ENV - - name: Install PHP with extensions uses: shivammathur/setup-php@v2 with: @@ -54,10 +47,6 @@ jobs: if: matrix.os == 'ubuntu-latest' run: echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_ENV - - name: Determine composer cache directory on Windows - if: matrix.os == 'windows-latest' - run: echo "COMPOSER_CACHE_DIR=~\AppData\Local\Composer" >> $GITHUB_ENV - - name: Cache dependencies installed with composer uses: actions/cache@v4 with: diff --git a/Classes/Authentication/OpenIdConnectProvider.php b/Classes/Authentication/OpenIdConnectProvider.php index 6b966bd..d63bbec 100644 --- a/Classes/Authentication/OpenIdConnectProvider.php +++ b/Classes/Authentication/OpenIdConnectProvider.php @@ -79,10 +79,10 @@ public function authenticate(TokenInterface $authenticationToken): void throw new UnsupportedAuthenticationTokenException(sprintf('The OpenID Connect authentication provider cannot authenticate the given token of type %s.', get_class($authenticationToken)), 1559805996); } if (!isset($this->options['roles']) && !isset($this->options['rolesFromClaims']) && !isset($this->options['addRolesFromExistingAccount'])) { - throw new \RuntimeException(sprintf('Either "roles", "rolesFromClaims" or "addRolesFromExistingAccount" must be specified in the configuration of OpenID Connect authentication provider'), 1559806095); + throw new \RuntimeException('Either "roles", "rolesFromClaims" or "addRolesFromExistingAccount" must be specified in the configuration of OpenID Connect authentication provider', 1559806095); } if (!isset($this->options['serviceName'])) { - throw new \RuntimeException(sprintf('Missing "serviceName" option in the configuration of OpenID Connect authentication provider'), 1561480057); + throw new \RuntimeException('Missing "serviceName" option in the configuration of OpenID Connect authentication provider', 1561480057); } if (!isset($this->options['accountIdentifierTokenValueName'])) { $this->options['accountIdentifierTokenValueName'] = 'sub'; @@ -103,7 +103,7 @@ public function authenticate(TokenInterface $authenticationToken): void throw new SecurityException('Open ID Connect: The identity token provided by the OIDC provider had an invalid signature', 1561479176); } $this->logger->debug(sprintf('OpenID Connect: Successfully verified signature of identity token with %s value "%s"', $this->options['accountIdentifierTokenValueName'], $identityToken->values[$this->options['accountIdentifierTokenValueName']] ?? 'unknown'), LogEnvironment::fromMethodName(__METHOD__)); - } catch (SecurityException\AuthenticationRequiredException $exception) { + } catch (SecurityException\AuthenticationRequiredException) { $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_NEEDED); return; } catch (SecurityException $exception) { @@ -261,13 +261,13 @@ private function getConfiguredRoles(IdentityToken $identityToken): array $this->logger->error(sprintf('OpenID Connect: Failed using account identifier from from identity token (%s) because the configured claim "%s" does not exist.', $identityToken->values['sub'] ?? '', $this->options['accountIdentifierTokenValueName']), LogEnvironment::fromMethodName(__METHOD__)); } else { $existingAccount = $this->accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($accountIdentifier, $this->name); - if (!$existingAccount instanceof Account) { - $this->logger->notice(sprintf('OpenID Connect: Could not add roles from existing account for identity token (%s) because the account "%s" (provider: %s) does not exist.', $identityToken->values['sub'] ?? '', $accountIdentifier, $this->name), LogEnvironment::fromMethodName(__METHOD__)); - } else { + if ($existingAccount instanceof Account) { foreach ($existingAccount->getRoles() as $role) { $roleIdentifiers[] = $role->getIdentifier(); } $this->logger->debug(sprintf('OpenID Connect: Added roles (identity token %s) from existing account "%s"', $identityToken->values['sub'] ?? '', $existingAccount->getAccountIdentifier()), LogEnvironment::fromMethodName(__METHOD__)); + } else { + $this->logger->notice(sprintf('OpenID Connect: Could not add roles from existing account for identity token (%s) because the account "%s" (provider: %s) does not exist.', $identityToken->values['sub'] ?? '', $accountIdentifier, $this->name), LogEnvironment::fromMethodName(__METHOD__)); } } } diff --git a/Classes/Authentication/OpenIdConnectToken.php b/Classes/Authentication/OpenIdConnectToken.php index 2965cf7..0d8e9d7 100644 --- a/Classes/Authentication/OpenIdConnectToken.php +++ b/Classes/Authentication/OpenIdConnectToken.php @@ -111,13 +111,13 @@ public function extractIdentityTokenFromRequest(string $cookieName): IdentityTok */ private function extractIdentityTokenFromAuthorizationHeader(string $authorizationHeader): IdentityToken { - if (strpos($this->authorizationHeader, 'Bearer ') !== 0) { + if (!str_starts_with($authorizationHeader, 'Bearer ')) { $this->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN); throw new AuthenticationRequiredException('Could not extract access token from Authorization header: "Bearer" keyword is missing', 1589283608); } try { - $jwt = substr($this->authorizationHeader, strlen('Bearer ')); + $jwt = substr($authorizationHeader, strlen('Bearer ')); $identityToken = IdentityToken::fromJwt($jwt); } catch (\InvalidArgumentException $exception) { $this->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS); diff --git a/Classes/Authentication/TokenArguments.php b/Classes/Authentication/TokenArguments.php index 07fd40f..774397f 100644 --- a/Classes/Authentication/TokenArguments.php +++ b/Classes/Authentication/TokenArguments.php @@ -41,12 +41,12 @@ public static function fromSignedString(string $encodedString): TokenArguments try { $payloadAsString = $returnArguments->hashService->validateAndStripHmac(base64_decode($encodedString)); $returnArguments->payload = json_decode($payloadAsString, true); - } catch (InvalidHashException $exception) { - throw new \InvalidArgumentException(sprintf('OpenID Connect: The token arguments were appended by an invalid HMAC'), 1560165515); + } catch (InvalidHashException) { + throw new \InvalidArgumentException('OpenID Connect: The token arguments were appended by an invalid HMAC', 1560165515); } if (!is_array($returnArguments->payload)) { - throw new \InvalidArgumentException(sprintf('OpenID Connect: Failed decoding token arguments payload from given string'), 1560162452); + throw new \InvalidArgumentException('OpenID Connect: Failed decoding token arguments payload from given string', 1560162452); } return $returnArguments; } @@ -78,11 +78,9 @@ public function offsetExists($offset): bool * @param mixed $offset * @return mixed */ - public function offsetGet($offset) + public function offsetGet($offset): mixed { - if (isset($this->payload[$offset])) { - return $this->payload[$offset]; - } + return $this->payload[$offset] ?? null; } /** @@ -91,14 +89,10 @@ public function offsetGet($offset) */ public function offsetSet($offset, $value): void { - switch($offset) { - case self::AUTHORIZATION_ID: - case self::SERVICE_NAME: - $this->payload[$offset] = $value; - break; - default: - throw new \InvalidArgumentException(sprintf('OpenID Connect: Invalid argument name "%s" for token arguments', $offset), 1560162220); - } + $this->payload[$offset] = match ($offset) { + self::AUTHORIZATION_ID, self::SERVICE_NAME => $value, + default => throw new \InvalidArgumentException(sprintf('OpenID Connect: Invalid argument name "%s" for token arguments', $offset), 1560162220), + }; } /** diff --git a/Classes/Command/OidcCommandController.php b/Classes/Command/OidcCommandController.php index bc06616..5fce366 100644 --- a/Classes/Command/OidcCommandController.php +++ b/Classes/Command/OidcCommandController.php @@ -74,7 +74,7 @@ public function discoverCommand(string $serviceName = null): void exit(1); } - $discoveredOptions = \GuzzleHttp\json_decode($response->getBody()->getContents(), true); + $discoveredOptions = json_decode($response->getBody()->getContents(), true); if (!is_array($discoveredOptions)) { $this->outputLine('Discovery endpoint returned invalid response'); exit(1); diff --git a/Classes/Http/SetJwtCookieMiddleware.php b/Classes/Http/SetJwtCookieMiddleware.php index b733894..9eac854 100644 --- a/Classes/Http/SetJwtCookieMiddleware.php +++ b/Classes/Http/SetJwtCookieMiddleware.php @@ -7,8 +7,6 @@ use Flownative\OpenIdConnect\Client\OAuthClient; use GuzzleHttp\Psr7\Query; use GuzzleHttp\Psr7\Utils; -use Neos\Flow\Http\Component\ComponentContext; -use Neos\Flow\Http\Component\TrustedProxiesComponent; use Neos\Flow\Http\Cookie; use Neos\Flow\Log\Utility\LogEnvironment; use Neos\Flow\Security\Context as SecurityContext; @@ -156,14 +154,6 @@ private function removeJwtCookie(ResponseInterface $response, string $cookieName */ private function withRedirectToRemoveOidcQueryParameters(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { - // Provide backwards-compatibility with Flow 6.3 and earlier, where the Trusted Proxies Middleware did not exist yet: - if (class_exists(TrustedProxiesComponent::class) && class_exists(ComponentContext::class) && $this->options['disableTrustedProxiesComponentCompatibility'] === false) { - $componentContext = new ComponentContext($request, $response); - $trustedProxiesComponent = new TrustedProxiesComponent(); - $trustedProxiesComponent->handle($componentContext); - $request = $componentContext->getHttpRequest(); - } - $queryParameters = Query::parse($request->getUri()->getQuery()); $authorizationIdQueryParameterName = OAuthClient::generateAuthorizationIdQueryParameterName(OAuthClient::SERVICE_TYPE); if (!isset($queryParameters[OpenIdConnectToken::OIDC_PARAMETER_NAME]) && !isset($queryParameters[$authorizationIdQueryParameterName])) { diff --git a/Classes/IdentityToken.php b/Classes/IdentityToken.php index 063ebf4..c4684db 100644 --- a/Classes/IdentityToken.php +++ b/Classes/IdentityToken.php @@ -4,6 +4,7 @@ use JsonException; use Lcobucci\JWT\Encoding\JoseEncoder; use Lcobucci\JWT\Token; +use Neos\Utility\Arrays; use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Crypt\RSA; use phpseclib3\Math\BigInteger; @@ -157,7 +158,7 @@ public function isExpiredAt(\DateTimeInterface $now): bool */ public function scopeContains(string $scopeIdentifier): bool { - $scopeIdentifiers = \Neos\Utility\Arrays::trimExplode(',', $this->values['scope'] ?? ''); + $scopeIdentifiers = Arrays::trimExplode(',', $this->values['scope'] ?? ''); return in_array($scopeIdentifier, $scopeIdentifiers, true); } @@ -200,7 +201,7 @@ private function getMatchingKeyForJws(array $keys, string $algorithm, ?string $k if ($keyIdentifier === null || !isset($key['kid']) || $key['kid'] === $keyIdentifier) { return $key; } - } else if (isset($key['alg']) && $key['alg'] === $algorithm && $key['kid'] === $keyIdentifier) { + } elseif (isset($key['alg']) && $key['alg'] === $algorithm && $key['kid'] === $keyIdentifier) { return $key; } } diff --git a/Classes/OAuthClient.php b/Classes/OAuthClient.php index ebdde2d..e67db52 100644 --- a/Classes/OAuthClient.php +++ b/Classes/OAuthClient.php @@ -56,7 +56,7 @@ public function getBaseUri(): string { $this->initializeOptionsIfNeeded(); if (!isset($this->options['issuer'])) { - throw new ConfigurationException(sprintf('Missing configuration issuer for service "%s" (%s). Either configure it explicitly via settings or make sure that auto-discovery returns "issuer".', $this->getServiceName(), $this->getServiceType()), 1559028091); + throw new ConfigurationException(sprintf('Missing configuration issuer for service "%s" (%s). Either configure it explicitly via settings or make sure that auto-discovery returns "issuer".', $this->getServiceName(), self::getServiceType()), 1559028091); } return $this->options['issuer']; } @@ -71,7 +71,7 @@ public function getAuthorizeTokenUri(): string { $this->initializeOptionsIfNeeded(); if (!isset($this->options['authorizationEndpoint']) || !is_string($this->options['authorizationEndpoint'])) { - throw new ConfigurationException(sprintf('Missing configuration authorizationEndpoint for service "%s" (%s). Either configure it explicitly via settings or make sure that auto-discovery returns "authorization_endpoint".', $this->getServiceName(), $this->getServiceType()), 1558612617); + throw new ConfigurationException(sprintf('Missing configuration authorizationEndpoint for service "%s" (%s). Either configure it explicitly via settings or make sure that auto-discovery returns "authorization_endpoint".', $this->getServiceName(), self::getServiceType()), 1558612617); } return $this->options['authorizationEndpoint']; } @@ -86,7 +86,7 @@ public function getAccessTokenUri(): string { $this->initializeOptionsIfNeeded(); if (!isset($this->options['tokenEndpoint']) || !is_string($this->options['tokenEndpoint'])) { - throw new ConfigurationException(sprintf('Missing configuration tokenEndpoint for service "%s" (%s). Either configure it explicitly via settings or make sure that auto-discovery returns "token_endpoint".', $this->getServiceName(), $this->getServiceType()), 1558615098); + throw new ConfigurationException(sprintf('Missing configuration tokenEndpoint for service "%s" (%s). Either configure it explicitly via settings or make sure that auto-discovery returns "token_endpoint".', $this->getServiceName(), self::getServiceType()), 1558615098); } return $this->options['tokenEndpoint']; } diff --git a/Classes/OpenIdConnectClient.php b/Classes/OpenIdConnectClient.php index 5ba1332..1925d3f 100644 --- a/Classes/OpenIdConnectClient.php +++ b/Classes/OpenIdConnectClient.php @@ -216,7 +216,7 @@ public function getAccessToken(string $serviceName, string $clientId, string $cl public function startAuthorization(UriInterface $returnToUri, string $scope): UriInterface { $returnArguments = (string)TokenArguments::fromArray([TokenArguments::SERVICE_NAME => $this->serviceName]); - if (strpos($returnArguments, 'ERROR') === 0) { + if (str_starts_with($returnArguments, 'ERROR')) { throw new \RuntimeException(substr($returnArguments, 6)); } $returnToUri = $returnToUri->withQuery(trim($returnToUri->getQuery() . '&' . OpenIdConnectToken::OIDC_PARAMETER_NAME . '=' . urlencode($returnArguments), '&')); @@ -288,7 +288,7 @@ public function getJwks(): array throw new ConnectionException(sprintf('OpenID Connect Client: Failed retrieving JWKS from %s: %s', $this->options['jwksUri'], $e->getMessage()), 1559211266); } - $response = \GuzzleHttp\json_decode($response->getBody()->getContents(), true); + $response = json_decode($response->getBody()->getContents(), true); if (!is_array($response) || !isset($response['keys'])) { throw new ServiceException(sprintf('OpenID Connect Client: Failed decoding response while retrieving JWKS from %s', $this->options['jwksUri']), 1559211340); } @@ -315,7 +315,7 @@ private function amendOptionsWithDiscovery(string $discoveryUri): void } $discoveredOptions = \GuzzleHttp\json_decode($response->getBody()->getContents(), true); if (!is_array($discoveredOptions)) { - throw new ConnectionException(sprintf('OpenID Connect Client: Discovery endpoint returned invalid response.'), 1554903349); + throw new ConnectionException('OpenID Connect Client: Discovery endpoint returned invalid response.', 1554903349); } $this->discoveryCache->set($cacheIdentifier, $discoveredOptions); $this->logger->info(sprintf('OpenID Connect Client: Auto-discovery via %s succeeded and stored into cache.', $discoveryUri), LogEnvironment::fromMethodName(__METHOD__)); diff --git a/composer.json b/composer.json index 1041f27..45e94b1 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "php": "8.1.* || 8.2.* || 8.3.* || 8.4.*", "neos/flow": "^7.3 || ^8.0 || ^9.0", "guzzlehttp/guzzle": "^6.0 || ^7.0", - "flownative/oauth2-client": "^4.0.0", + "flownative/oauth2-client": "^4.1.1", "phpseclib/phpseclib": "^3.0.0", "lcobucci/jwt": "^4.1", "psr/http-server-middleware": "^1.0" From a3eaba9c6d1f0efedadf332e8db88d3b026b6e85 Mon Sep 17 00:00:00 2001 From: Karsten Dambekalns Date: Tue, 10 Dec 2024 23:50:04 +0100 Subject: [PATCH 5/6] Test cleanup --- Tests/Unit/IdentityTokenTest.php | 17 ++++++++-------- Tests/Unit/OpenIdConnectClientTest.php | 24 +++++++++++------------ Tests/Unit/SetJwtCookieMiddlewareTest.php | 12 ++++++------ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/Tests/Unit/IdentityTokenTest.php b/Tests/Unit/IdentityTokenTest.php index 8c126f2..3a4ce44 100644 --- a/Tests/Unit/IdentityTokenTest.php +++ b/Tests/Unit/IdentityTokenTest.php @@ -11,12 +11,11 @@ * source code. */ -use JsonException; use PHPUnit\Framework\TestCase; class IdentityTokenTest extends TestCase { - public function invalidJsonStrings(): array + public static function invalidJsonStrings(): array { return [ ['xy', 1559204596], @@ -54,9 +53,9 @@ public function fromJsonSetsValuesCorrectly(): void $json = 'eyJraWQiOiJkZmViZTVlNy00MjMyLTQ0NjQtOGYyZS0xNTE2ODFhMGQxNzMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lkLmV4YW1wbGUuY29tIiwiYXVkIjoiQCFEREQ1LjM3MEQuODU0Ny5GRkQ5ITAwMDEhQTFDOS45MkMxITAwMDghMTNEQi41NEQ4LjY1REUuMjc2MSIsImV4cCI6MTU1OTIwNTU2MCwiaWF0IjoxNTU5MjAxOTYwLCJhdXRoX3RpbWUiOjE1NTkyMDE5NTksImF0X2hhc2giOiJfU1BHdHM1OUlTbFdNSHhzMmEwM3N3Iiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwic3ViIjoiVVdBWWZ6em1jYU5BWnlfQzhhOFVvVXhNbWhUMUlsY0tsWEc4VG5Xa3lJTSJ9.VsOdosHuRWVaoacWG1CNJl0IZrHH-HbFTCZDcQDtFPSma13sHO-C69tm_HTjHX5DnMX6B_lDCgu3A8AsSZIQEG71z_Mnd2uxHoUrKUtHr8iM9bhpPKMnaXx9jr0O1EtKAJDLkz4qdzNunyOU7Ud94Lc8YxIjf7FZH_-jJc0UqFyFKY2rdEiZQVATNG94F-SIWA4CK5FZtW47TCL8EPBUzP8gGG8g6eMBEIfv80uWQxpJ59_UB91D8U6zSOiA4JrFDBRLkIX2kGnUZ7eu1G-4O6TglL_Id0oMeJdNEsMARYKHGmYZjvHGFVoLyoxca1KDK5dlcnLsYyxfKsZWNrTaqA'; $identityToken = IdentityToken::fromJwt($json); - $this->assertSame('https://id.example.com', $identityToken->values['iss']); - $this->assertSame('UWAYfzzmcaNAZy_C8a8UoUxMmhT1IlcKlXG8TnWkyIM', $identityToken->values['sub']); - $this->assertSame('@!DDD5.370D.8547.FFD9!0001!A1C9.92C1!0008!13DB.54D8.65DE.2761', $identityToken->values['aud']); + static::assertSame('https://id.example.com', $identityToken->values['iss']); + static::assertSame('UWAYfzzmcaNAZy_C8a8UoUxMmhT1IlcKlXG8TnWkyIM', $identityToken->values['sub']); + static::assertSame('@!DDD5.370D.8547.FFD9!0001!A1C9.92C1!0008!13DB.54D8.65DE.2761', $identityToken->values['aud']); } /** @@ -67,8 +66,8 @@ public function asJwtReturnsTokenAsString(): void { $json = 'eyJraWQiOiJkZmViZTVlNy00MjMyLTQ0NjQtOGYyZS0xNTE2ODFhMGQxNzMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL2lkLmV4YW1wbGUuY29tIiwiYXVkIjoiQCFEREQ1LjM3MEQuODU0Ny5GRkQ5ITAwMDEhQTFDOS45MkMxITAwMDghMTNEQi41NEQ4LjY1REUuMjc2MSIsImV4cCI6MTU1OTIwNTU2MCwiaWF0IjoxNTU5MjAxOTYwLCJhdXRoX3RpbWUiOjE1NTkyMDE5NTksImF0X2hhc2giOiJfU1BHdHM1OUlTbFdNSHhzMmEwM3N3Iiwib3hPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwic3ViIjoiVVdBWWZ6em1jYU5BWnlfQzhhOFVvVXhNbWhUMUlsY0tsWEc4VG5Xa3lJTSJ9.VsOdosHuRWVaoacWG1CNJl0IZrHH-HbFTCZDcQDtFPSma13sHO-C69tm_HTjHX5DnMX6B_lDCgu3A8AsSZIQEG71z_Mnd2uxHoUrKUtHr8iM9bhpPKMnaXx9jr0O1EtKAJDLkz4qdzNunyOU7Ud94Lc8YxIjf7FZH_-jJc0UqFyFKY2rdEiZQVATNG94F-SIWA4CK5FZtW47TCL8EPBUzP8gGG8g6eMBEIfv80uWQxpJ59_UB91D8U6zSOiA4JrFDBRLkIX2kGnUZ7eu1G-4O6TglL_Id0oMeJdNEsMARYKHGmYZjvHGFVoLyoxca1KDK5dlcnLsYyxfKsZWNrTaqA'; $identityToken = IdentityToken::fromJwt($json); - $this->assertSame($identityToken->asJwt(), $json); - $this->assertSame((string)$identityToken, $json); + static::assertSame($identityToken->asJwt(), $json); + static::assertSame((string)$identityToken, $json); } /** @@ -80,7 +79,7 @@ public function isExpiredAtReturnsCorrectResult(): void $identityToken = IdentityToken::fromJwt($json); # Token expired at 2019-05-30 08:39:20.000000 - $this->assertFalse($identityToken->isExpiredAt(\DateTimeImmutable::createFromFormat('d.m.Y H:i:s', '29.05.2019 09:00:00'))); - $this->assertTrue($identityToken->isExpiredAt(\DateTimeImmutable::createFromFormat('d.m.Y H:i:s', '31.05.2019 09:00:00'))); + static::assertFalse($identityToken->isExpiredAt(\DateTimeImmutable::createFromFormat('d.m.Y H:i:s', '29.05.2019 09:00:00'))); + static::assertTrue($identityToken->isExpiredAt(\DateTimeImmutable::createFromFormat('d.m.Y H:i:s', '31.05.2019 09:00:00'))); } } diff --git a/Tests/Unit/OpenIdConnectClientTest.php b/Tests/Unit/OpenIdConnectClientTest.php index 5f81c65..bf9f5b8 100644 --- a/Tests/Unit/OpenIdConnectClientTest.php +++ b/Tests/Unit/OpenIdConnectClientTest.php @@ -105,14 +105,14 @@ public function getJwksReturnsJwksAndStoresItInCache(): void $expectedJwks = json_decode($this->exampleJwksJson, true, 512, JSON_THROW_ON_ERROR); $cacheEntryIdentifier = sha1($this->settings['services']['test']['options']['jwksUri']); - $mockHttpClient->expects($this->once())->method('request')->with('GET', $this->settings['services']['test']['options']['jwksUri'])->willReturn($mockHttpResponse); - $mockHttpResponse->expects($this->once())->method('getBody')->willReturn($mockHttpBody); - $mockHttpBody->expects($this->once())->method('getContents')->willReturn(json_encode(['keys' => json_decode($this->exampleJwksJson, true, 512, JSON_THROW_ON_ERROR)], JSON_THROW_ON_ERROR, 512)); + $mockHttpClient->expects(static::once())->method('request')->with('GET', $this->settings['services']['test']['options']['jwksUri'])->willReturn($mockHttpResponse); + $mockHttpResponse->expects(static::once())->method('getBody')->willReturn($mockHttpBody); + $mockHttpBody->expects(static::once())->method('getContents')->willReturn(json_encode(['keys' => json_decode($this->exampleJwksJson, true, 512, JSON_THROW_ON_ERROR)], JSON_THROW_ON_ERROR, 512)); $actualJwks = $this->oidcClient->getJwks(); - $this->assertSame($expectedJwks, $actualJwks); - $this->assertSame($expectedJwks, $this->jwksCache->get($cacheEntryIdentifier)); + static::assertSame($expectedJwks, $actualJwks); + static::assertSame($expectedJwks, $this->jwksCache->get($cacheEntryIdentifier)); } /** @@ -128,7 +128,7 @@ public function getJwksThrowsExceptionOnFailedDiscoveryRequest(): void $this->inject($this->oidcClient, 'httpClient', $mockHttpClient); $this->oidcClient->initializeObject(); - $mockHttpClient->expects($this->once())->method('request')->willThrowException(new ConnectException('Something wrong', $mockHttpRequest)); + $mockHttpClient->expects(static::once())->method('request')->willThrowException(new ConnectException('Something wrong', $mockHttpRequest)); $this->expectExceptionCode(1559211266); $this->oidcClient->getJwks(); @@ -148,9 +148,9 @@ public function getJwksThrowsExceptionOnMalformedResponseFromDiscoveryService(): $this->inject($this->oidcClient, 'httpClient', $mockHttpClient); $this->oidcClient->initializeObject(); - $mockHttpClient->expects($this->once())->method('request')->with('GET', $this->settings['services']['test']['options']['jwksUri'])->willReturn($mockHttpResponse); - $mockHttpResponse->expects($this->once())->method('getBody')->willReturn($mockHttpBody); - $mockHttpBody->expects($this->once())->method('getContents')->willReturn(json_encode(['something invalid' => json_decode($this->exampleJwksJson, true, 512, JSON_THROW_ON_ERROR)], JSON_THROW_ON_ERROR, 512)); + $mockHttpClient->expects(static::once())->method('request')->with('GET', $this->settings['services']['test']['options']['jwksUri'])->willReturn($mockHttpResponse); + $mockHttpResponse->expects(static::once())->method('getBody')->willReturn($mockHttpBody); + $mockHttpBody->expects(static::once())->method('getContents')->willReturn(json_encode(['something invalid' => json_decode($this->exampleJwksJson, true, 512, JSON_THROW_ON_ERROR)], JSON_THROW_ON_ERROR, 512)); $this->expectExceptionCode(1559211340); $this->oidcClient->getJwks(); @@ -169,7 +169,7 @@ public function getJwksReturnsJwksFromCacheIfItExists(): void $cacheEntryIdentifier = sha1($this->settings['services']['test']['options']['jwksUri']); $this->jwksCache->set($cacheEntryIdentifier, $expectedJwks); - $this->assertSame($expectedJwks, $this->oidcClient->getJwks()); + static::assertSame($expectedJwks, $this->oidcClient->getJwks()); } /** @@ -196,8 +196,8 @@ public function getAccessTokenReturnsAccessTokenFromAuthorization(): void $actualAccessToken = $this->oidcClient->getAccessToken($serviceName, $clientId, $clientSecret, $scope); - $this->assertSame($expectedAccessToken->getToken(), $actualAccessToken->getToken()); - $this->assertSame($expectedAccessToken->getExpires(), $actualAccessToken->getExpires()); + static::assertSame($expectedAccessToken->getToken(), $actualAccessToken->getToken()); + static::assertSame($expectedAccessToken->getExpires(), $actualAccessToken->getExpires()); } /** diff --git a/Tests/Unit/SetJwtCookieMiddlewareTest.php b/Tests/Unit/SetJwtCookieMiddlewareTest.php index db6d787..daa5fb6 100644 --- a/Tests/Unit/SetJwtCookieMiddlewareTest.php +++ b/Tests/Unit/SetJwtCookieMiddlewareTest.php @@ -100,7 +100,7 @@ public function processReturnsUnalteredResponseOfInnerMiddlewareChainIfNoOidcAut self::assertSame($response, $this->mockOriginalResponse); } - public function removeJwtCookieDataProvider(): array + public static function removeJwtCookieDataProvider(): array { return [ 'no authenticated tokens' => ['options' => [], 'authenticationProviderConfiguration' => [], 'authenticatedTokens' => [], 'activeCookies' => ['flownative_oidc_jwt'], 'expectedCookieHeader' => null], @@ -129,7 +129,7 @@ public function removeJwtCookieDataProvider(): array * @test * @dataProvider removeJwtCookieDataProvider */ - public function removeJwtCookieTests(array $options, array $authenticationProviderConfiguration, array $authenticatedTokens, array $activeCookies, string $expectedCookieHeader = null): void + public function removeJwtCookieTests(array $options, array $authenticationProviderConfiguration, array $authenticatedTokens, array $activeCookies, ?string $expectedCookieHeader = null): void { $middleware = $this->getMiddleware($options, $authenticationProviderConfiguration); $this->mockSecurityContext->method('isInitialized')->willReturn(true); @@ -151,7 +151,7 @@ public function removeJwtCookieTests(array $options, array $authenticationProvid } } - public function setJwtCookieDataProvider(): array + public static function setJwtCookieDataProvider(): array { return [ 'no authenticated tokens' => ['options' => [], 'authenticationProviderConfiguration' => [], 'authenticatedTokens' => [], 'activeCookies' => ['flownative_oidc_jwt'], 'expectedCookieHeader' => null], @@ -180,7 +180,7 @@ public function setJwtCookieDataProvider(): array * @test * @dataProvider setJwtCookieDataProvider */ - public function setJwtCookieTests(array $options, array $authenticationProviderConfiguration, array $authenticatedTokens, array $activeCookies, string $expectedCookieHeader = null): void + public function setJwtCookieTests(array $options, array $authenticationProviderConfiguration, array $authenticatedTokens, array $activeCookies, ?string $expectedCookieHeader = null): void { $middleware = $this->getMiddleware($options, $authenticationProviderConfiguration); $this->mockSecurityContext->method('isInitialized')->willReturn(true); @@ -226,7 +226,7 @@ public function processDoesNotSetCookieHeaderIfAuthenticatedAccountDoesNotContai self::assertFalse($response->hasHeader('Set-Cookie')); } - public function removeOidcQueryParametersDataProvider(): array + public static function removeOidcQueryParametersDataProvider(): array { return [ ['requestUri' => 'http://localhost', 'expectedLocationHeader' => null], @@ -244,7 +244,7 @@ public function removeOidcQueryParametersDataProvider(): array * @test * @dataProvider removeOidcQueryParametersDataProvider */ - public function removeOidcQueryParametersTests(string $requestUri, string $expectedLocationHeader = null): void + public function removeOidcQueryParametersTests(string $requestUri, ?string $expectedLocationHeader = null): void { $middleware = $this->getMiddleware(); $this->mockSecurityContext->method('isInitialized')->willReturn(true); From 20048494f46d0a5a4dc7f06bcf9ef1d491d574cd Mon Sep 17 00:00:00 2001 From: Karsten Dambekalns Date: Wed, 11 Dec 2024 11:35:12 +0100 Subject: [PATCH 6/6] Raise used PhpUnit version to ^9.6.21 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 45e94b1..0d29a12 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "psr/http-server-middleware": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": "^9.6.21", "phpunit/php-code-coverage": "*" }, "autoload": {