public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Commit
[Web] update stevenmaguire/oauth2-keycloak and firebase/php-jwt
cee771a3
data/web/inc/lib/composer.json | 2 +-
data/web/inc/lib/composer.lock | 47 +--
data/web/inc/lib/vendor/composer/installed.json | 49 +--
data/web/inc/lib/vendor/composer/installed.php | 16 +-
.../inc/lib/vendor/firebase/php-jwt/CHANGELOG.md | 117 +++++++
data/web/inc/lib/vendor/firebase/php-jwt/README.md | 342 ++++++++++++------
.../inc/lib/vendor/firebase/php-jwt/composer.json | 12 +-
.../vendor/firebase/php-jwt/src/CachedKeySet.php | 258 ++++++++++++++
.../inc/lib/vendor/firebase/php-jwt/src/JWK.php | 201 +++++++++--
.../inc/lib/vendor/firebase/php-jwt/src/JWT.php | 389 +++++++++++----------
.../inc/lib/vendor/firebase/php-jwt/src/Key.php | 35 +-
.../stevenmaguire/oauth2-keycloak/.travis.yml | 9 +-
.../vendor/stevenmaguire/oauth2-keycloak/README.md | 1 +
.../stevenmaguire/oauth2-keycloak/composer.json | 17 +-
.../stevenmaguire/oauth2-keycloak/phpunit.xml.dist | 45 ++-
.../test/src/Provider/KeycloakTest.php | 124 ++++---
16 files changed, 1209 insertions(+), 455 deletions(-)
create mode 100644 data/web/inc/lib/vendor/firebase/php-jwt/CHANGELOG.md
create mode 100644 data/web/inc/lib/vendor/firebase/php-jwt/src/CachedKeySet.php
Diff
diff --git a/data/web/inc/lib/composer.json b/data/web/inc/lib/composer.json
index c2fef5fb..a803291f 100644
--- a/data/web/inc/lib/composer.json
+++ b/data/web/inc/lib/composer.json
@@ -10,7 +10,7 @@
"mustangostang/spyc": "^0.6.3",
"directorytree/ldaprecord": "^2.4",
"twig/twig": "^3.0",
- "stevenmaguire/oauth2-keycloak": "^3.2",
+ "stevenmaguire/oauth2-keycloak": "^4.0",
"league/oauth2-client": "^2.7"
}
}
diff --git a/data/web/inc/lib/composer.lock b/data/web/inc/lib/composer.lock
index 349056af..0d55230c 100644
--- a/data/web/inc/lib/composer.lock
+++ b/data/web/inc/lib/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "ee35a2bf8c80a87b6825c3e86635f709",
+ "content-hash": "8f5a147cdb147b935a158b86f47a4747",
"packages": [
{
"name": "bshaffer/oauth2-server-php",
@@ -218,25 +218,31 @@
},
{
"name": "firebase/php-jwt",
- "version": "v5.5.1",
+ "version": "v6.5.0",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
- "reference": "83b609028194aa042ea33b5af2d41a7427de80e6"
+ "reference": "e94e7353302b0c11ec3cfff7180cd0b1743975d2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6",
- "reference": "83b609028194aa042ea33b5af2d41a7427de80e6",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/e94e7353302b0c11ec3cfff7180cd0b1743975d2",
+ "reference": "e94e7353302b0c11ec3cfff7180cd0b1743975d2",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": "^7.4||^8.0"
},
"require-dev": {
- "phpunit/phpunit": ">=4.8 <=9"
+ "guzzlehttp/guzzle": "^6.5||^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^1.0||^2.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
},
"suggest": {
+ "ext-sodium": "Support EdDSA (Ed25519) signatures",
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
},
"type": "library",
@@ -269,9 +275,9 @@
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
- "source": "https://github.com/firebase/php-jwt/tree/v5.5.1"
+ "source": "https://github.com/firebase/php-jwt/tree/v6.5.0"
},
- "time": "2021-11-08T20:18:51+00:00"
+ "time": "2023-05-12T15:47:07+00:00"
},
{
"name": "guzzlehttp/guzzle",
@@ -1703,26 +1709,27 @@
},
{
"name": "stevenmaguire/oauth2-keycloak",
- "version": "3.2.0",
+ "version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/stevenmaguire/oauth2-keycloak.git",
- "reference": "34e4824f5fa26aa8e90f1258859c75570c12d27a"
+ "reference": "05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/stevenmaguire/oauth2-keycloak/zipball/34e4824f5fa26aa8e90f1258859c75570c12d27a",
- "reference": "34e4824f5fa26aa8e90f1258859c75570c12d27a",
+ "url": "https://api.github.com/repos/stevenmaguire/oauth2-keycloak/zipball/05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d",
+ "reference": "05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d",
"shasum": ""
},
"require": {
- "firebase/php-jwt": "~4.0|~5.0",
- "league/oauth2-client": "^2.0"
+ "firebase/php-jwt": "^4.0 || ^5.0 || ^6.0",
+ "league/oauth2-client": "^2.0",
+ "php": "~7.2 || ~8.0"
},
"require-dev": {
- "mockery/mockery": "~0.9",
- "phpunit/phpunit": "~4.0",
- "squizlabs/php_codesniffer": "~2.0"
+ "mockery/mockery": "~1.5.0",
+ "phpunit/phpunit": "~9.6.4",
+ "squizlabs/php_codesniffer": "~3.7.0"
},
"type": "library",
"extra": {
@@ -1757,9 +1764,9 @@
],
"support": {
"issues": "https://github.com/stevenmaguire/oauth2-keycloak/issues",
- "source": "https://github.com/stevenmaguire/oauth2-keycloak/tree/3.2.0"
+ "source": "https://github.com/stevenmaguire/oauth2-keycloak/tree/4.0.0"
},
- "time": "2022-12-16T12:46:38+00:00"
+ "time": "2023-03-14T09:43:47+00:00"
},
{
"name": "symfony/deprecation-contracts",
diff --git a/data/web/inc/lib/vendor/composer/installed.json b/data/web/inc/lib/vendor/composer/installed.json
index ef7cac48..0b772551 100644
--- a/data/web/inc/lib/vendor/composer/installed.json
+++ b/data/web/inc/lib/vendor/composer/installed.json
@@ -217,29 +217,35 @@
},
{
"name": "firebase/php-jwt",
- "version": "v5.5.1",
- "version_normalized": "5.5.1.0",
+ "version": "v6.5.0",
+ "version_normalized": "6.5.0.0",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
- "reference": "83b609028194aa042ea33b5af2d41a7427de80e6"
+ "reference": "e94e7353302b0c11ec3cfff7180cd0b1743975d2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6",
- "reference": "83b609028194aa042ea33b5af2d41a7427de80e6",
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/e94e7353302b0c11ec3cfff7180cd0b1743975d2",
+ "reference": "e94e7353302b0c11ec3cfff7180cd0b1743975d2",
"shasum": ""
},
"require": {
- "php": ">=5.3.0"
+ "php": "^7.4||^8.0"
},
"require-dev": {
- "phpunit/phpunit": ">=4.8 <=9"
+ "guzzlehttp/guzzle": "^6.5||^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^1.0||^2.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
},
"suggest": {
+ "ext-sodium": "Support EdDSA (Ed25519) signatures",
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
},
- "time": "2021-11-08T20:18:51+00:00",
+ "time": "2023-05-12T15:47:07+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@@ -271,7 +277,7 @@
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
- "source": "https://github.com/firebase/php-jwt/tree/v5.5.1"
+ "source": "https://github.com/firebase/php-jwt/tree/v6.5.0"
},
"install-path": "../firebase/php-jwt"
},
@@ -1759,29 +1765,30 @@
},
{
"name": "stevenmaguire/oauth2-keycloak",
- "version": "3.2.0",
- "version_normalized": "3.2.0.0",
+ "version": "4.0.0",
+ "version_normalized": "4.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/stevenmaguire/oauth2-keycloak.git",
- "reference": "34e4824f5fa26aa8e90f1258859c75570c12d27a"
+ "reference": "05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/stevenmaguire/oauth2-keycloak/zipball/34e4824f5fa26aa8e90f1258859c75570c12d27a",
- "reference": "34e4824f5fa26aa8e90f1258859c75570c12d27a",
+ "url": "https://api.github.com/repos/stevenmaguire/oauth2-keycloak/zipball/05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d",
+ "reference": "05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d",
"shasum": ""
},
"require": {
- "firebase/php-jwt": "~4.0|~5.0",
- "league/oauth2-client": "^2.0"
+ "firebase/php-jwt": "^4.0 || ^5.0 || ^6.0",
+ "league/oauth2-client": "^2.0",
+ "php": "~7.2 || ~8.0"
},
"require-dev": {
- "mockery/mockery": "~0.9",
- "phpunit/phpunit": "~4.0",
- "squizlabs/php_codesniffer": "~2.0"
+ "mockery/mockery": "~1.5.0",
+ "phpunit/phpunit": "~9.6.4",
+ "squizlabs/php_codesniffer": "~3.7.0"
},
- "time": "2022-12-16T12:46:38+00:00",
+ "time": "2023-03-14T09:43:47+00:00",
"type": "library",
"extra": {
"branch-alias": {
@@ -1816,7 +1823,7 @@
],
"support": {
"issues": "https://github.com/stevenmaguire/oauth2-keycloak/issues",
- "source": "https://github.com/stevenmaguire/oauth2-keycloak/tree/3.2.0"
+ "source": "https://github.com/stevenmaguire/oauth2-keycloak/tree/4.0.0"
},
"install-path": "../stevenmaguire/oauth2-keycloak"
},
diff --git a/data/web/inc/lib/vendor/composer/installed.php b/data/web/inc/lib/vendor/composer/installed.php
index a9737b06..d7cc7774 100644
--- a/data/web/inc/lib/vendor/composer/installed.php
+++ b/data/web/inc/lib/vendor/composer/installed.php
@@ -3,7 +3,7 @@
'name' => '__root__',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => '07edec4ea50b8eedae10c28eba0b4b2774df537e',
+ 'reference' => '34e7b3f613661fe2b3c3eb1d316a63dfe111022e',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -13,7 +13,7 @@
'__root__' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => '07edec4ea50b8eedae10c28eba0b4b2774df537e',
+ 'reference' => '34e7b3f613661fe2b3c3eb1d316a63dfe111022e',
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -53,9 +53,9 @@
),
),
'firebase/php-jwt' => array(
- 'pretty_version' => 'v5.5.1',
- 'version' => '5.5.1.0',
- 'reference' => '83b609028194aa042ea33b5af2d41a7427de80e6',
+ 'pretty_version' => 'v6.5.0',
+ 'version' => '6.5.0.0',
+ 'reference' => 'e94e7353302b0c11ec3cfff7180cd0b1743975d2',
'type' => 'library',
'install_path' => __DIR__ . '/../firebase/php-jwt',
'aliases' => array(),
@@ -275,9 +275,9 @@
'dev_requirement' => false,
),
'stevenmaguire/oauth2-keycloak' => array(
- 'pretty_version' => '3.2.0',
- 'version' => '3.2.0.0',
- 'reference' => '34e4824f5fa26aa8e90f1258859c75570c12d27a',
+ 'pretty_version' => '4.0.0',
+ 'version' => '4.0.0.0',
+ 'reference' => '05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d',
'type' => 'library',
'install_path' => __DIR__ . '/../stevenmaguire/oauth2-keycloak',
'aliases' => array(),
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/CHANGELOG.md b/data/web/inc/lib/vendor/firebase/php-jwt/CHANGELOG.md
new file mode 100644
index 00000000..35e97fe8
--- /dev/null
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/CHANGELOG.md
@@ -0,0 +1,117 @@
+# Changelog
+
+## [6.5.0](https://github.com/firebase/php-jwt/compare/v6.4.0...v6.5.0) (2023-05-12)
+
+
+### Bug Fixes
+
+* allow KID of '0' ([#505](https://github.com/firebase/php-jwt/issues/505)) ([9dc46a9](https://github.com/firebase/php-jwt/commit/9dc46a9c3e5801294249cfd2554c5363c9f9326a))
+
+
+### Miscellaneous Chores
+
+* drop support for PHP 7.3 ([#495](https://github.com/firebase/php-jwt/issues/495))
+
+## [6.4.0](https://github.com/firebase/php-jwt/compare/v6.3.2...v6.4.0) (2023-02-08)
+
+
+### Features
+
+* add support for W3C ES256K ([#462](https://github.com/firebase/php-jwt/issues/462)) ([213924f](https://github.com/firebase/php-jwt/commit/213924f51936291fbbca99158b11bd4ae56c2c95))
+* improve caching by only decoding jwks when necessary ([#486](https://github.com/firebase/php-jwt/issues/486)) ([78d3ed1](https://github.com/firebase/php-jwt/commit/78d3ed1073553f7d0bbffa6c2010009a0d483d5c))
+
+## [6.3.2](https://github.com/firebase/php-jwt/compare/v6.3.1...v6.3.2) (2022-11-01)
+
+
+### Bug Fixes
+
+* check kid before using as array index ([bad1b04](https://github.com/firebase/php-jwt/commit/bad1b040d0c736bbf86814c6b5ae614f517cf7bd))
+
+## [6.3.1](https://github.com/firebase/php-jwt/compare/v6.3.0...v6.3.1) (2022-11-01)
+
+
+### Bug Fixes
+
+* casing of GET for PSR compat ([#451](https://github.com/firebase/php-jwt/issues/451)) ([60b52b7](https://github.com/firebase/php-jwt/commit/60b52b71978790eafcf3b95cfbd83db0439e8d22))
+* string interpolation format for php 8.2 ([#446](https://github.com/firebase/php-jwt/issues/446)) ([2e07d8a](https://github.com/firebase/php-jwt/commit/2e07d8a1524d12b69b110ad649f17461d068b8f2))
+
+## 6.3.0 / 2022-07-15
+
+ - Added ES256 support to JWK parsing ([#399](https://github.com/firebase/php-jwt/pull/399))
+ - Fixed potential caching error in `CachedKeySet` by caching jwks as strings ([#435](https://github.com/firebase/php-jwt/pull/435))
+
+## 6.2.0 / 2022-05-14
+
+ - Added `CachedKeySet` ([#397](https://github.com/firebase/php-jwt/pull/397))
+ - Added `$defaultAlg` parameter to `JWT::parseKey` and `JWT::parseKeySet` ([#426](https://github.com/firebase/php-jwt/pull/426)).
+
+## 6.1.0 / 2022-03-23
+
+ - Drop support for PHP 5.3, 5.4, 5.5, 5.6, and 7.0
+ - Add parameter typing and return types where possible
+
+## 6.0.0 / 2022-01-24
+
+ - **Backwards-Compatibility Breaking Changes**: See the [Release Notes](https://github.com/firebase/php-jwt/releases/tag/v6.0.0) for more information.
+ - New Key object to prevent key/algorithm type confusion (#365)
+ - Add JWK support (#273)
+ - Add ES256 support (#256)
+ - Add ES384 support (#324)
+ - Add Ed25519 support (#343)
+
+## 5.0.0 / 2017-06-26
+- Support RS384 and RS512.
+ See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
+- Add an example for RS256 openssl.
+ See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
+- Detect invalid Base64 encoding in signature.
+ See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
+- Update `JWT::verify` to handle OpenSSL errors.
+ See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
+- Add `array` type hinting to `decode` method
+ See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
+- Add all JSON error types.
+ See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
+- Bugfix 'kid' not in given key list.
+ See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
+- Miscellaneous cleanup, documentation and test fixes.
+ See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
+ [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
+ [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
+ [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
+
+## 4.0.0 / 2016-07-17
+- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
+- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
+- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
+- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
+
+## 3.0.0 / 2015-07-22
+- Minimum PHP version updated from `5.2.0` to `5.3.0`.
+- Add `\Firebase\JWT` namespace. See
+[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
+[@Dashron](https://github.com/Dashron)!
+- Require a non-empty key to decode and verify a JWT. See
+[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
+[@sjones608](https://github.com/sjones608)!
+- Cleaner documentation blocks in the code. See
+[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
+[@johanderuijter](https://github.com/johanderuijter)!
+
+## 2.2.0 / 2015-06-22
+- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
+[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
+[@mcocaro](https://github.com/mcocaro)!
+
+## 2.1.0 / 2015-05-20
+- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
+between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
+- Add support for passing an object implementing the `ArrayAccess` interface for
+`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
+
+## 2.0.0 / 2015-04-01
+- **Note**: It is strongly recommended that you update to > v2.0.0 to address
+ known security vulnerabilities in prior versions when both symmetric and
+ asymmetric keys are used together.
+- Update signature for `JWT::decode(...)` to require an array of supported
+ algorithms to use when verifying token signatures.
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/README.md b/data/web/inc/lib/vendor/firebase/php-jwt/README.md
index 1d392cd1..f0382667 100644
--- a/data/web/inc/lib/vendor/firebase/php-jwt/README.md
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/README.md
@@ -1,4 +1,4 @@
-[](https://travis-ci.org/firebase/php-jwt)
+
[](https://packagist.org/packages/firebase/php-jwt)
[](https://packagist.org/packages/firebase/php-jwt)
[](https://packagist.org/packages/firebase/php-jwt)
@@ -29,13 +29,13 @@ Example
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
-$key = "example_key";
-$payload = array(
- "iss" => "http://example.org",
- "aud" => "http://example.com",
- "iat" => 1356999524,
- "nbf" => 1357000000
-);
+$key = 'example_key';
+$payload = [
+ 'iss' => 'http://example.org',
+ 'aud' => 'http://example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
/**
* IMPORTANT:
@@ -65,6 +65,40 @@ $decoded_array = (array) $decoded;
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
```
+Example encode/decode headers
+-------
+Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
+this library. This is because without verifying the JWT, the header values could have been tampered with.
+Any value pulled from an unverified header should be treated as if it could be any string sent in from an
+attacker. If this is something you still want to do in your application for whatever reason, it's possible to
+decode the header values manually simply by calling `json_decode` and `base64_decode` on the JWT
+header part:
+```php
+use Firebase\JWT\JWT;
+
+$key = 'example_key';
+$payload = [
+ 'iss' => 'http://example.org',
+ 'aud' => 'http://example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$headers = [
+ 'x-forwarded-for' => 'www.google.com'
+];
+
+// Encode headers in the JWT string
+$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
+
+// Decode headers from the JWT string WITHOUT validation
+// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
+// These headers could be any value sent by an attacker.
+list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
+$decoded = json_decode(base64_decode($headersB64), true);
+
+print_r($decoded);
+```
Example with RS256 (openssl)
----------------------------
```php
@@ -73,37 +107,52 @@ use Firebase\JWT\Key;
$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn
-vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9
-5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB
-AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz
-bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J
-Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1
-cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5
-5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck
-ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe
-k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb
-qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k
-eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm
-B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM=
+MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
+M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
+JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
+78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
+HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
+WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
+6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
+VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
+oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
+c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
+h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
+bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
+39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
+3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
+vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
+6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
+OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
+nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
+xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
+8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
+hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
+YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
+DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
+RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
+2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
-----END RSA PRIVATE KEY-----
EOD;
$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
-MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H
-4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t
-0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4
-ehde/zUxo6UvS7UrBQIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
+fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
+hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
+u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
+opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
+TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
+wQIDAQAB
-----END PUBLIC KEY-----
EOD;
-$payload = array(
- "iss" => "example.org",
- "aud" => "example.com",
- "iat" => 1356999524,
- "nbf" => 1357000000
-);
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";
@@ -139,12 +188,12 @@ $privateKey = openssl_pkey_get_private(
$passphrase
);
-$payload = array(
- "iss" => "example.org",
- "aud" => "example.com",
- "iat" => 1356999524,
- "nbf" => 1357000000
-);
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";
@@ -173,12 +222,12 @@ $privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
-$payload = array(
- "iss" => "example.org",
- "aud" => "example.com",
- "iat" => 1356999524,
- "nbf" => 1357000000
-);
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
echo "Encode:\n" . print_r($jwt, true) . "\n";
@@ -187,6 +236,44 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";
````
+Example with multiple keys
+--------------------------
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\Key;
+
+// Example RSA keys from previous example
+// $privateKey1 = '...';
+// $publicKey1 = '...';
+
+// Example EdDSA keys from previous example
+// $privateKey2 = '...';
+// $publicKey2 = '...';
+
+$payload = [
+ 'iss' => 'example.org',
+ 'aud' => 'example.com',
+ 'iat' => 1356999524,
+ 'nbf' => 1357000000
+];
+
+$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
+$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
+echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
+echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
+
+$keys = [
+ 'kid1' => new Key($publicKey1, 'RS256'),
+ 'kid2' => new Key($publicKey2, 'EdDSA'),
+];
+
+$decoded1 = JWT::decode($jwt1, $keys);
+$decoded2 = JWT::decode($jwt2, $keys);
+
+echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
+echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";
+```
+
Using JWKs
----------
@@ -198,72 +285,115 @@ use Firebase\JWT\JWT;
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
$jwks = ['keys' => []];
-// JWK::parseKeySet($jwks) returns an associative array of **kid** to private
-// key. Pass this as the second parameter to JWT::decode.
-// NOTE: The deprecated $supportedAlgorithm must be supplied when parsing from JWK.
-JWT::decode($payload, JWK::parseKeySet($jwks), $supportedAlgorithm);
+// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
+// objects. Pass this as the second parameter to JWT::decode.
+JWT::decode($payload, JWK::parseKeySet($jwks));
```
-Changelog
----------
-
-#### 5.0.0 / 2017-06-26
-- Support RS384 and RS512.
- See [#117](https://github.com/firebase/php-jwt/pull/117). Thanks [@joostfaassen](https://github.com/joostfaassen)!
-- Add an example for RS256 openssl.
- See [#125](https://github.com/firebase/php-jwt/pull/125). Thanks [@akeeman](https://github.com/akeeman)!
-- Detect invalid Base64 encoding in signature.
- See [#162](https://github.com/firebase/php-jwt/pull/162). Thanks [@psignoret](https://github.com/psignoret)!
-- Update `JWT::verify` to handle OpenSSL errors.
- See [#159](https://github.com/firebase/php-jwt/pull/159). Thanks [@bshaffer](https://github.com/bshaffer)!
-- Add `array` type hinting to `decode` method
- See [#101](https://github.com/firebase/php-jwt/pull/101). Thanks [@hywak](https://github.com/hywak)!
-- Add all JSON error types.
- See [#110](https://github.com/firebase/php-jwt/pull/110). Thanks [@gbalduzzi](https://github.com/gbalduzzi)!
-- Bugfix 'kid' not in given key list.
- See [#129](https://github.com/firebase/php-jwt/pull/129). Thanks [@stampycode](https://github.com/stampycode)!
-- Miscellaneous cleanup, documentation and test fixes.
- See [#107](https://github.com/firebase/php-jwt/pull/107), [#115](https://github.com/firebase/php-jwt/pull/115),
- [#160](https://github.com/firebase/php-jwt/pull/160), [#161](https://github.com/firebase/php-jwt/pull/161), and
- [#165](https://github.com/firebase/php-jwt/pull/165). Thanks [@akeeman](https://github.com/akeeman),
- [@chinedufn](https://github.com/chinedufn), and [@bshaffer](https://github.com/bshaffer)!
-
-#### 4.0.0 / 2016-07-17
-- Add support for late static binding. See [#88](https://github.com/firebase/php-jwt/pull/88) for details. Thanks to [@chappy84](https://github.com/chappy84)!
-- Use static `$timestamp` instead of `time()` to improve unit testing. See [#93](https://github.com/firebase/php-jwt/pull/93) for details. Thanks to [@josephmcdermott](https://github.com/josephmcdermott)!
-- Fixes to exceptions classes. See [#81](https://github.com/firebase/php-jwt/pull/81) for details. Thanks to [@Maks3w](https://github.com/Maks3w)!
-- Fixes to PHPDoc. See [#76](https://github.com/firebase/php-jwt/pull/76) for details. Thanks to [@akeeman](https://github.com/akeeman)!
-
-#### 3.0.0 / 2015-07-22
-- Minimum PHP version updated from `5.2.0` to `5.3.0`.
-- Add `\Firebase\JWT` namespace. See
-[#59](https://github.com/firebase/php-jwt/pull/59) for details. Thanks to
-[@Dashron](https://github.com/Dashron)!
-- Require a non-empty key to decode and verify a JWT. See
-[#60](https://github.com/firebase/php-jwt/pull/60) for details. Thanks to
-[@sjones608](https://github.com/sjones608)!
-- Cleaner documentation blocks in the code. See
-[#62](https://github.com/firebase/php-jwt/pull/62) for details. Thanks to
-[@johanderuijter](https://github.com/johanderuijter)!
-
-#### 2.2.0 / 2015-06-22
-- Add support for adding custom, optional JWT headers to `JWT::encode()`. See
-[#53](https://github.com/firebase/php-jwt/pull/53/files) for details. Thanks to
-[@mcocaro](https://github.com/mcocaro)!
-
-#### 2.1.0 / 2015-05-20
-- Add support for adding a leeway to `JWT:decode()` that accounts for clock skew
-between signing and verifying entities. Thanks to [@lcabral](https://github.com/lcabral)!
-- Add support for passing an object implementing the `ArrayAccess` interface for
-`$keys` argument in `JWT::decode()`. Thanks to [@aztech-dev](https://github.com/aztech-dev)!
-
-#### 2.0.0 / 2015-04-01
-- **Note**: It is strongly recommended that you update to > v2.0.0 to address
- known security vulnerabilities in prior versions when both symmetric and
- asymmetric keys are used together.
-- Update signature for `JWT::decode(...)` to require an array of supported
- algorithms to use when verifying token signatures.
+Using Cached Key Sets
+---------------------
+
+The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
+This has the following advantages:
+
+1. The results are cached for performance.
+2. If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
+3. If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
+```php
+use Firebase\JWT\CachedKeySet;
+use Firebase\JWT\JWT;
+
+// The URI for the JWKS you wish to cache the results from
+$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
+
+// Create an HTTP client (can be any PSR-7 compatible HTTP client)
+$httpClient = new GuzzleHttp\Client();
+
+// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
+$httpFactory = new GuzzleHttp\Psr\HttpFactory();
+
+// Create a cache item pool (can be any PSR-6 compatible cache item pool)
+$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
+
+$keySet = new CachedKeySet(
+ $jwksUri,
+ $httpClient,
+ $httpFactory,
+ $cacheItemPool,
+ null, // $expiresAfter int seconds to set the JWKS to expire
+ true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
+);
+
+$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
+$decoded = JWT::decode($jwt, $keySet);
+```
+
+Miscellaneous
+-------------
+
+#### Exception Handling
+
+When a call to `JWT::decode` is invalid, it will throw one of the following exceptions:
+
+```php
+use Firebase\JWT\JWT;
+use Firebase\JWT\SignatureInvalidException;
+use Firebase\JWT\BeforeValidException;
+use Firebase\JWT\ExpiredException;
+use DomainException;
+use InvalidArgumentException;
+use UnexpectedValueException;
+
+try {
+ $decoded = JWT::decode($payload, $keys);
+} catch (InvalidArgumentException $e) {
+ // provided key/key-array is empty or malformed.
+} catch (DomainException $e) {
+ // provided algorithm is unsupported OR
+ // provided key is invalid OR
+ // unknown error thrown in openSSL or libsodium OR
+ // libsodium is required but not available.
+} catch (SignatureInvalidException $e) {
+ // provided JWT signature verification failed.
+} catch (BeforeValidException $e) {
+ // provided JWT is trying to be used before "nbf" claim OR
+ // provided JWT is trying to be used before "iat" claim.
+} catch (ExpiredException $e) {
+ // provided JWT is trying to be used after "exp" claim.
+} catch (UnexpectedValueException $e) {
+ // provided JWT is malformed OR
+ // provided JWT is missing an algorithm / using an unsupported algorithm OR
+ // provided JWT algorithm does not match provided key OR
+ // provided key ID in key/key-array is empty or invalid.
+}
+```
+
+All exceptions in the `Firebase\JWT` namespace extend `UnexpectedValueException`, and can be simplified
+like this:
+
+```php
+try {
+ $decoded = JWT::decode($payload, $keys);
+} catch (LogicException $e) {
+ // errors having to do with environmental setup or malformed JWT Keys
+} catch (UnexpectedValueException $e) {
+ // errors having to do with JWT signature and claims
+}
+```
+
+#### Casting to array
+
+The return value of `JWT::decode` is the generic PHP object `stdClass`. If you'd like to handle with arrays
+instead, you can do the following:
+
+```php
+// return type is stdClass
+$decoded = JWT::decode($payload, $keys);
+
+// cast to array
+$decoded = json_decode(json_encode($decoded), true);
+```
Tests
-----
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/composer.json b/data/web/inc/lib/vendor/firebase/php-jwt/composer.json
index 6146e2dc..e23dfe37 100644
--- a/data/web/inc/lib/vendor/firebase/php-jwt/composer.json
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/composer.json
@@ -20,10 +20,11 @@
],
"license": "BSD-3-Clause",
"require": {
- "php": ">=5.3.0"
+ "php": "^7.4||^8.0"
},
"suggest": {
- "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
+ "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present",
+ "ext-sodium": "Support EdDSA (Ed25519) signatures"
},
"autoload": {
"psr-4": {
@@ -31,6 +32,11 @@
}
},
"require-dev": {
- "phpunit/phpunit": ">=4.8 <=9"
+ "guzzlehttp/guzzle": "^6.5||^7.4",
+ "phpspec/prophecy-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.5",
+ "psr/cache": "^1.0||^2.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0"
}
}
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/src/CachedKeySet.php b/data/web/inc/lib/vendor/firebase/php-jwt/src/CachedKeySet.php
new file mode 100644
index 00000000..baf801f1
--- /dev/null
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/src/CachedKeySet.php
@@ -0,0 +1,258 @@
+<?php
+
+namespace Firebase\JWT;
+
+use ArrayAccess;
+use InvalidArgumentException;
+use LogicException;
+use OutOfBoundsException;
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\CacheItemPoolInterface;
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use RuntimeException;
+use UnexpectedValueException;
+
+/**
+ * @implements ArrayAccess<string, Key>
+ */
+class CachedKeySet implements ArrayAccess
+{
+ /**
+ * @var string
+ */
+ private $jwksUri;
+ /**
+ * @var ClientInterface
+ */
+ private $httpClient;
+ /**
+ * @var RequestFactoryInterface
+ */
+ private $httpFactory;
+ /**
+ * @var CacheItemPoolInterface
+ */
+ private $cache;
+ /**
+ * @var ?int
+ */
+ private $expiresAfter;
+ /**
+ * @var ?CacheItemInterface
+ */
+ private $cacheItem;
+ /**
+ * @var array<string, array<mixed>>
+ */
+ private $keySet;
+ /**
+ * @var string
+ */
+ private $cacheKey;
+ /**
+ * @var string
+ */
+ private $cacheKeyPrefix = 'jwks';
+ /**
+ * @var int
+ */
+ private $maxKeyLength = 64;
+ /**
+ * @var bool
+ */
+ private $rateLimit;
+ /**
+ * @var string
+ */
+ private $rateLimitCacheKey;
+ /**
+ * @var int
+ */
+ private $maxCallsPerMinute = 10;
+ /**
+ * @var string|null
+ */
+ private $defaultAlg;
+
+ public function __construct(
+ string $jwksUri,
+ ClientInterface $httpClient,
+ RequestFactoryInterface $httpFactory,
+ CacheItemPoolInterface $cache,
+ int $expiresAfter = null,
+ bool $rateLimit = false,
+ string $defaultAlg = null
+ ) {
+ $this->jwksUri = $jwksUri;
+ $this->httpClient = $httpClient;
+ $this->httpFactory = $httpFactory;
+ $this->cache = $cache;
+ $this->expiresAfter = $expiresAfter;
+ $this->rateLimit = $rateLimit;
+ $this->defaultAlg = $defaultAlg;
+ $this->setCacheKeys();
+ }
+
+ /**
+ * @param string $keyId
+ * @return Key
+ */
+ public function offsetGet($keyId): Key
+ {
+ if (!$this->keyIdExists($keyId)) {
+ throw new OutOfBoundsException('Key ID not found');
+ }
+ return JWK::parseKey($this->keySet[$keyId], $this->defaultAlg);
+ }
+
+ /**
+ * @param string $keyId
+ * @return bool
+ */
+ public function offsetExists($keyId): bool
+ {
+ return $this->keyIdExists($keyId);
+ }
+
+ /**
+ * @param string $offset
+ * @param Key $value
+ */
+ public function offsetSet($offset, $value): void
+ {
+ throw new LogicException('Method not implemented');
+ }
+
+ /**
+ * @param string $offset
+ */
+ public function offsetUnset($offset): void
+ {
+ throw new LogicException('Method not implemented');
+ }
+
+ /**
+ * @return array<mixed>
+ */
+ private function formatJwksForCache(string $jwks): array
+ {
+ $jwks = json_decode($jwks, true);
+
+ if (!isset($jwks['keys'])) {
+ throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
+ }
+
+ if (empty($jwks['keys'])) {
+ throw new InvalidArgumentException('JWK Set did not contain any keys');
+ }
+
+ $keys = [];
+ foreach ($jwks['keys'] as $k => $v) {
+ $kid = isset($v['kid']) ? $v['kid'] : $k;
+ $keys[(string) $kid] = $v;
+ }
+
+ return $keys;
+ }
+
+ private function keyIdExists(string $keyId): bool
+ {
+ if (null === $this->keySet) {
+ $item = $this->getCacheItem();
+ // Try to load keys from cache
+ if ($item->isHit()) {
+ // item found! retrieve it
+ $this->keySet = $item->get();
+ // If the cached item is a string, the JWKS response was cached (previous behavior).
+ // Parse this into expected format array<kid, jwk> instead.
+ if (\is_string($this->keySet)) {
+ $this->keySet = $this->formatJwksForCache($this->keySet);
+ }
+ }
+ }
+
+ if (!isset($this->keySet[$keyId])) {
+ if ($this->rateLimitExceeded()) {
+ return false;
+ }
+ $request = $this->httpFactory->createRequest('GET', $this->jwksUri);
+ $jwksResponse = $this->httpClient->sendRequest($request);
+ $this->keySet = $this->formatJwksForCache((string) $jwksResponse->getBody());
+
+ if (!isset($this->keySet[$keyId])) {
+ return false;
+ }
+
+ $item = $this->getCacheItem();
+ $item->set($this->keySet);
+ if ($this->expiresAfter) {
+ $item->expiresAfter($this->expiresAfter);
+ }
+ $this->cache->save($item);
+ }
+
+ return true;
+ }
+
+ private function rateLimitExceeded(): bool
+ {
+ if (!$this->rateLimit) {
+ return false;
+ }
+
+ $cacheItem = $this->cache->getItem($this->rateLimitCacheKey);
+ if (!$cacheItem->isHit()) {
+ $cacheItem->expiresAfter(1); // # of calls are cached each minute
+ }
+
+ $callsPerMinute = (int) $cacheItem->get();
+ if (++$callsPerMinute > $this->maxCallsPerMinute) {
+ return true;
+ }
+ $cacheItem->set($callsPerMinute);
+ $this->cache->save($cacheItem);
+ return false;
+ }
+
+ private function getCacheItem(): CacheItemInterface
+ {
+ if (\is_null($this->cacheItem)) {
+ $this->cacheItem = $this->cache->getItem($this->cacheKey);
+ }
+
+ return $this->cacheItem;
+ }
+
+ private function setCacheKeys(): void
+ {
+ if (empty($this->jwksUri)) {
+ throw new RuntimeException('JWKS URI is empty');
+ }
+
+ // ensure we do not have illegal characters
+ $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $this->jwksUri);
+
+ // add prefix
+ $key = $this->cacheKeyPrefix . $key;
+
+ // Hash keys if they exceed $maxKeyLength of 64
+ if (\strlen($key) > $this->maxKeyLength) {
+ $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
+ }
+
+ $this->cacheKey = $key;
+
+ if ($this->rateLimit) {
+ // add prefix
+ $rateLimitKey = $this->cacheKeyPrefix . 'ratelimit' . $key;
+
+ // Hash keys if they exceed $maxKeyLength of 64
+ if (\strlen($rateLimitKey) > $this->maxKeyLength) {
+ $rateLimitKey = substr(hash('sha256', $rateLimitKey), 0, $this->maxKeyLength);
+ }
+
+ $this->rateLimitCacheKey = $rateLimitKey;
+ }
+ }
+}
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/src/JWK.php b/data/web/inc/lib/vendor/firebase/php-jwt/src/JWK.php
index 981a9ba7..c7eff8ae 100644
--- a/data/web/inc/lib/vendor/firebase/php-jwt/src/JWK.php
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/src/JWK.php
@@ -20,12 +20,25 @@ use UnexpectedValueException;
*/
class JWK
{
+ private const OID = '1.2.840.10045.2.1';
+ private const ASN1_OBJECT_IDENTIFIER = 0x06;
+ private const ASN1_SEQUENCE = 0x10; // also defined in JWT
+ private const ASN1_BIT_STRING = 0x03;
+ private const EC_CURVES = [
+ 'P-256' => '1.2.840.10045.3.1.7', // Len: 64
+ 'secp256k1' => '1.3.132.0.10', // Len: 64
+ // 'P-384' => '1.3.132.0.34', // Len: 96 (not yet supported)
+ // 'P-521' => '1.3.132.0.35', // Len: 132 (not supported)
+ ];
+
/**
* Parse a set of JWK keys
*
- * @param array $jwks The JSON Web Key Set as an associative array
+ * @param array<mixed> $jwks The JSON Web Key Set as an associative array
+ * @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
+ * JSON Web Key Set
*
- * @return array An associative array that represents the set of keys
+ * @return array<string, Key> An associative array of key IDs (kid) to Key objects
*
* @throws InvalidArgumentException Provided JWK Set is empty
* @throws UnexpectedValueException Provided JWK Set was invalid
@@ -33,21 +46,22 @@ class JWK
*
* @uses parseKey
*/
- public static function parseKeySet(array $jwks)
+ public static function parseKeySet(array $jwks, string $defaultAlg = null): array
{
- $keys = array();
+ $keys = [];
if (!isset($jwks['keys'])) {
throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
}
+
if (empty($jwks['keys'])) {
throw new InvalidArgumentException('JWK Set did not contain any keys');
}
foreach ($jwks['keys'] as $k => $v) {
$kid = isset($v['kid']) ? $v['kid'] : $k;
- if ($key = self::parseKey($v)) {
- $keys[$kid] = $key;
+ if ($key = self::parseKey($v, $defaultAlg)) {
+ $keys[(string) $kid] = $key;
}
}
@@ -61,9 +75,11 @@ class JWK
/**
* Parse a JWK key
*
- * @param array $jwk An individual JWK
+ * @param array<mixed> $jwk An individual JWK
+ * @param string $defaultAlg The algorithm for the Key object if "alg" is not set in the
+ * JSON Web Key Set
*
- * @return resource|array An associative array that represents the key
+ * @return Key The key object for the JWK
*
* @throws InvalidArgumentException Provided JWK is empty
* @throws UnexpectedValueException Provided JWK was invalid
@@ -71,15 +87,27 @@ class JWK
*
* @uses createPemFromModulusAndExponent
*/
- public static function parseKey(array $jwk)
+ public static function parseKey(array $jwk, string $defaultAlg = null): ?Key
{
if (empty($jwk)) {
throw new InvalidArgumentException('JWK must not be empty');
}
+
if (!isset($jwk['kty'])) {
throw new UnexpectedValueException('JWK must contain a "kty" parameter');
}
+ if (!isset($jwk['alg'])) {
+ if (\is_null($defaultAlg)) {
+ // The "alg" parameter is optional in a KTY, but an algorithm is required
+ // for parsing in this library. Use the $defaultAlg parameter when parsing the
+ // key set in order to prevent this error.
+ // @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
+ throw new UnexpectedValueException('JWK must contain an "alg" parameter');
+ }
+ $jwk['alg'] = $defaultAlg;
+ }
+
switch ($jwk['kty']) {
case 'RSA':
if (!empty($jwk['d'])) {
@@ -96,11 +124,72 @@ class JWK
'OpenSSL error: ' . \openssl_error_string()
);
}
- return $publicKey;
+ return new Key($publicKey, $jwk['alg']);
+ case 'EC':
+ if (isset($jwk['d'])) {
+ // The key is actually a private key
+ throw new UnexpectedValueException('Key data must be for a public key');
+ }
+
+ if (empty($jwk['crv'])) {
+ throw new UnexpectedValueException('crv not set');
+ }
+
+ if (!isset(self::EC_CURVES[$jwk['crv']])) {
+ throw new DomainException('Unrecognised or unsupported EC curve');
+ }
+
+ if (empty($jwk['x']) || empty($jwk['y'])) {
+ throw new UnexpectedValueException('x and y not set');
+ }
+
+ $publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
+ return new Key($publicKey, $jwk['alg']);
default:
// Currently only RSA is supported
break;
}
+
+ return null;
+ }
+
+ /**
+ * Converts the EC JWK values to pem format.
+ *
+ * @param string $crv The EC curve (only P-256 is supported)
+ * @param string $x The EC x-coordinate
+ * @param string $y The EC y-coordinate
+ *
+ * @return string
+ */
+ private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
+ {
+ $pem =
+ self::encodeDER(
+ self::ASN1_SEQUENCE,
+ self::encodeDER(
+ self::ASN1_SEQUENCE,
+ self::encodeDER(
+ self::ASN1_OBJECT_IDENTIFIER,
+ self::encodeOID(self::OID)
+ )
+ . self::encodeDER(
+ self::ASN1_OBJECT_IDENTIFIER,
+ self::encodeOID(self::EC_CURVES[$crv])
+ )
+ ) .
+ self::encodeDER(
+ self::ASN1_BIT_STRING,
+ \chr(0x00) . \chr(0x04)
+ . JWT::urlsafeB64Decode($x)
+ . JWT::urlsafeB64Decode($y)
+ )
+ );
+
+ return sprintf(
+ "-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
+ wordwrap(base64_encode($pem), 64, "\n", true)
+ );
}
/**
@@ -113,22 +202,22 @@ class JWK
*
* @uses encodeLength
*/
- private static function createPemFromModulusAndExponent($n, $e)
- {
- $modulus = JWT::urlsafeB64Decode($n);
- $publicExponent = JWT::urlsafeB64Decode($e);
+ private static function createPemFromModulusAndExponent(
+ string $n,
+ string $e
+ ): string {
+ $mod = JWT::urlsafeB64Decode($n);
+ $exp = JWT::urlsafeB64Decode($e);
- $components = array(
- 'modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus),
- 'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent)
- );
+ $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod);
+ $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);
$rsaPublicKey = \pack(
'Ca*a*a*',
48,
- self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])),
- $components['modulus'],
- $components['publicExponent']
+ self::encodeLength(\strlen($modulus) + \strlen($publicExponent)),
+ $modulus,
+ $publicExponent
);
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
@@ -143,11 +232,9 @@ class JWK
$rsaOID . $rsaPublicKey
);
- $rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
+ return "-----BEGIN PUBLIC KEY-----\r\n" .
\chunk_split(\base64_encode($rsaPublicKey), 64) .
'-----END PUBLIC KEY-----';
-
- return $rsaPublicKey;
}
/**
@@ -159,7 +246,7 @@ class JWK
* @param int $length
* @return string
*/
- private static function encodeLength($length)
+ private static function encodeLength(int $length): string
{
if ($length <= 0x7F) {
return \chr($length);
@@ -169,4 +256,68 @@ class JWK
return \pack('Ca*', 0x80 | \strlen($temp), $temp);
}
+
+ /**
+ * Encodes a value into a DER object.
+ * Also defined in Firebase\JWT\JWT
+ *
+ * @param int $type DER tag
+ * @param string $value the value to encode
+ * @return string the encoded object
+ */
+ private static function encodeDER(int $type, string $value): string
+ {
+ $tag_header = 0;
+ if ($type === self::ASN1_SEQUENCE) {
+ $tag_header |= 0x20;
+ }
+
+ // Type
+ $der = \chr($tag_header | $type);
+
+ // Length
+ $der .= \chr(\strlen($value));
+
+ return $der . $value;
+ }
+
+ /**
+ * Encodes a string into a DER-encoded OID.
+ *
+ * @param string $oid the OID string
+ * @return string the binary DER-encoded OID
+ */
+ private static function encodeOID(string $oid): string
+ {
+ $octets = explode('.', $oid);
+
+ // Get the first octet
+ $first = (int) array_shift($octets);
+ $second = (int) array_shift($octets);
+ $oid = \chr($first * 40 + $second);
+
+ // Iterate over subsequent octets
+ foreach ($octets as $octet) {
+ if ($octet == 0) {
+ $oid .= \chr(0x00);
+ continue;
+ }
+ $bin = '';
+
+ while ($octet) {
+ $bin .= \chr(0x80 | ($octet & 0x7f));
+ $octet >>= 7;
+ }
+ $bin[0] = $bin[0] & \chr(0x7f);
+
+ // Convert to big endian if necessary
+ if (pack('V', 65534) == pack('L', 65534)) {
+ $oid .= strrev($bin);
+ } else {
+ $oid .= $bin;
+ }
+ }
+
+ return $oid;
+ }
}
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/src/JWT.php b/data/web/inc/lib/vendor/firebase/php-jwt/src/JWT.php
index ec1641bc..c83ff099 100644
--- a/data/web/inc/lib/vendor/firebase/php-jwt/src/JWT.php
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/src/JWT.php
@@ -3,12 +3,14 @@
namespace Firebase\JWT;
use ArrayAccess;
+use DateTime;
use DomainException;
use Exception;
use InvalidArgumentException;
use OpenSSLAsymmetricKey;
+use OpenSSLCertificate;
+use stdClass;
use UnexpectedValueException;
-use DateTime;
/**
* JSON Web Token implementation, based on this spec:
@@ -25,52 +27,62 @@ use DateTime;
*/
class JWT
{
- const ASN1_INTEGER = 0x02;
- const ASN1_SEQUENCE = 0x10;
- const ASN1_BIT_STRING = 0x03;
+ private const ASN1_INTEGER = 0x02;
+ private const ASN1_SEQUENCE = 0x10;
+ private const ASN1_BIT_STRING = 0x03;
/**
* When checking nbf, iat or expiration times,
* we want to provide some extra leeway time to
* account for clock skew.
+ *
+ * @var int
*/
public static $leeway = 0;
/**
* Allow the current timestamp to be specified.
* Useful for fixing a value within unit testing.
- *
* Will default to PHP time() value if null.
+ *
+ * @var ?int
*/
public static $timestamp = null;
- public static $supported_algs = array(
- 'ES384' => array('openssl', 'SHA384'),
- 'ES256' => array('openssl', 'SHA256'),
- 'HS256' => array('hash_hmac', 'SHA256'),
- 'HS384' => array('hash_hmac', 'SHA384'),
- 'HS512' => array('hash_hmac', 'SHA512'),
- 'RS256' => array('openssl', 'SHA256'),
- 'RS384' => array('openssl', 'SHA384'),
- 'RS512' => array('openssl', 'SHA512'),
- 'EdDSA' => array('sodium_crypto', 'EdDSA'),
- );
+ /**
+ * @var array<string, string[]>
+ */
+ public static $supported_algs = [
+ 'ES384' => ['openssl', 'SHA384'],
+ 'ES256' => ['openssl', 'SHA256'],
+ 'ES256K' => ['openssl', 'SHA256'],
+ 'HS256' => ['hash_hmac', 'SHA256'],
+ 'HS384' => ['hash_hmac', 'SHA384'],
+ 'HS512' => ['hash_hmac', 'SHA512'],
+ 'RS256' => ['openssl', 'SHA256'],
+ 'RS384' => ['openssl', 'SHA384'],
+ 'RS512' => ['openssl', 'SHA512'],
+ 'EdDSA' => ['sodium_crypto', 'EdDSA'],
+ ];
/**
* Decodes a JWT string into a PHP object.
*
- * @param string $jwt The JWT
- * @param Key|array<Key>|mixed $keyOrKeyArray The Key or array of Key objects.
- * If the algorithm used is asymmetric, this is the public key
- * Each Key object contains an algorithm and matching key.
- * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
- * 'HS512', 'RS256', 'RS384', and 'RS512'
- * @param array $allowed_algs [DEPRECATED] List of supported verification algorithms. Only
- * should be used for backwards compatibility.
- *
- * @return object The JWT's payload as a PHP object
- *
- * @throws InvalidArgumentException Provided JWT was empty
+ * @param string $jwt The JWT
+ * @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray The Key or associative array of key IDs
+ * (kid) to Key objects.
+ * If the algorithm used is asymmetric, this is
+ * the public key.
+ * Each Key object contains an algorithm and
+ * matching key.
+ * Supported algorithms are 'ES384','ES256',
+ * 'HS256', 'HS384', 'HS512', 'RS256', 'RS384'
+ * and 'RS512'.
+ *
+ * @return stdClass The JWT's payload as a PHP object
+ *
+ * @throws InvalidArgumentException Provided key/key-array was empty or malformed
+ * @throws DomainException Provided JWT is malformed
* @throws UnexpectedValueException Provided JWT was invalid
* @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
* @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
@@ -80,27 +92,37 @@ class JWT
* @uses jsonDecode
* @uses urlsafeB64Decode
*/
- public static function decode($jwt, $keyOrKeyArray, array $allowed_algs = array())
- {
+ public static function decode(
+ string $jwt,
+ $keyOrKeyArray
+ ): stdClass {
+ // Validate JWT
$timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
if (empty($keyOrKeyArray)) {
throw new InvalidArgumentException('Key may not be empty');
}
$tks = \explode('.', $jwt);
- if (\count($tks) != 3) {
+ if (\count($tks) !== 3) {
throw new UnexpectedValueException('Wrong number of segments');
}
list($headb64, $bodyb64, $cryptob64) = $tks;
- if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64)))) {
+ $headerRaw = static::urlsafeB64Decode($headb64);
+ if (null === ($header = static::jsonDecode($headerRaw))) {
throw new UnexpectedValueException('Invalid header encoding');
}
- if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64))) {
+ $payloadRaw = static::urlsafeB64Decode($bodyb64);
+ if (null === ($payload = static::jsonDecode($payloadRaw))) {
throw new UnexpectedValueException('Invalid claims encoding');
}
- if (false === ($sig = static::urlsafeB64Decode($cryptob64))) {
- throw new UnexpectedValueException('Invalid signature encoding');
+ if (\is_array($payload)) {
+ // prevent PHP Fatal Error in edge-cases when payload is empty array
+ $payload = (object) $payload;
+ }
+ if (!$payload instanceof stdClass) {
+ throw new UnexpectedValueException('Payload must be a JSON object');
}
+ $sig = static::urlsafeB64Decode($cryptob64);
if (empty($header->alg)) {
throw new UnexpectedValueException('Empty algorithm');
}
@@ -108,31 +130,18 @@ class JWT
throw new UnexpectedValueException('Algorithm not supported');
}
- list($keyMaterial, $algorithm) = self::getKeyMaterialAndAlgorithm(
- $keyOrKeyArray,
- empty($header->kid) ? null : $header->kid
- );
+ $key = self::getKey($keyOrKeyArray, property_exists($header, 'kid') ? $header->kid : null);
- if (empty($algorithm)) {
- // Use deprecated "allowed_algs" to determine if the algorithm is supported.
- // This opens up the possibility of an attack in some implementations.
- // @see https://github.com/firebase/php-jwt/issues/351
- if (!\in_array($header->alg, $allowed_algs)) {
- throw new UnexpectedValueException('Algorithm not allowed');
- }
- } else {
- // Check the algorithm
- if (!self::constantTimeEquals($algorithm, $header->alg)) {
- // See issue #351
- throw new UnexpectedValueException('Incorrect key for this algorithm');
- }
+ // Check the algorithm
+ if (!self::constantTimeEquals($key->getAlgorithm(), $header->alg)) {
+ // See issue #351
+ throw new UnexpectedValueException('Incorrect key for this algorithm');
}
- if ($header->alg === 'ES256' || $header->alg === 'ES384') {
- // OpenSSL expects an ASN.1 DER sequence for ES256/ES384 signatures
+ if (\in_array($header->alg, ['ES256', 'ES256K', 'ES384'], true)) {
+ // OpenSSL expects an ASN.1 DER sequence for ES256/ES256K/ES384 signatures
$sig = self::signatureToDER($sig);
}
-
- if (!static::verify("$headb64.$bodyb64", $sig, $keyMaterial, $header->alg)) {
+ if (!self::verify("{$headb64}.{$bodyb64}", $sig, $key->getKeyMaterial(), $header->alg)) {
throw new SignatureInvalidException('Signature verification failed');
}
@@ -162,34 +171,37 @@ class JWT
}
/**
- * Converts and signs a PHP object or array into a JWT string.
+ * Converts and signs a PHP array into a JWT string.
*
- * @param object|array $payload PHP object or array
- * @param string|resource $key The secret key.
- * If the algorithm used is asymmetric, this is the private key
- * @param string $alg The signing algorithm.
- * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
- * 'HS512', 'RS256', 'RS384', and 'RS512'
- * @param mixed $keyId
- * @param array $head An array with header elements to attach
+ * @param array<mixed> $payload PHP array
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
+ * @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
+ * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
+ * @param string $keyId
+ * @param array<string, string> $head An array with header elements to attach
*
* @return string A signed JWT
*
* @uses jsonEncode
* @uses urlsafeB64Encode
*/
- public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)
- {
- $header = array('typ' => 'JWT', 'alg' => $alg);
+ public static function encode(
+ array $payload,
+ $key,
+ string $alg,
+ string $keyId = null,
+ array $head = null
+ ): string {
+ $header = ['typ' => 'JWT', 'alg' => $alg];
if ($keyId !== null) {
$header['kid'] = $keyId;
}
if (isset($head) && \is_array($head)) {
$header = \array_merge($head, $header);
}
- $segments = array();
- $segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
- $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
+ $segments = [];
+ $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($header));
+ $segments[] = static::urlsafeB64Encode((string) static::jsonEncode($payload));
$signing_input = \implode('.', $segments);
$signature = static::sign($signing_input, $key, $alg);
@@ -201,67 +213,84 @@ class JWT
/**
* Sign a string with a given key and algorithm.
*
- * @param string $msg The message to sign
- * @param string|resource $key The secret key
- * @param string $alg The signing algorithm.
- * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
- * 'HS512', 'RS256', 'RS384', and 'RS512'
+ * @param string $msg The message to sign
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $key The secret key.
+ * @param string $alg Supported algorithms are 'ES384','ES256', 'ES256K', 'HS256',
+ * 'HS384', 'HS512', 'RS256', 'RS384', and 'RS512'
*
* @return string An encrypted message
*
* @throws DomainException Unsupported algorithm or bad key was specified
*/
- public static function sign($msg, $key, $alg = 'HS256')
- {
+ public static function sign(
+ string $msg,
+ $key,
+ string $alg
+ ): string {
if (empty(static::$supported_algs[$alg])) {
throw new DomainException('Algorithm not supported');
}
list($function, $algorithm) = static::$supported_algs[$alg];
switch ($function) {
case 'hash_hmac':
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException('key must be a string when using hmac');
+ }
return \hash_hmac($algorithm, $msg, $key, true);
case 'openssl':
$signature = '';
- $success = \openssl_sign($msg, $signature, $key, $algorithm);
+ $success = \openssl_sign($msg, $signature, $key, $algorithm); // @phpstan-ignore-line
if (!$success) {
- throw new DomainException("OpenSSL unable to sign data");
+ throw new DomainException('OpenSSL unable to sign data');
}
- if ($alg === 'ES256') {
+ if ($alg === 'ES256' || $alg === 'ES256K') {
$signature = self::signatureFromDER($signature, 256);
} elseif ($alg === 'ES384') {
$signature = self::signatureFromDER($signature, 384);
}
return $signature;
case 'sodium_crypto':
- if (!function_exists('sodium_crypto_sign_detached')) {
+ if (!\function_exists('sodium_crypto_sign_detached')) {
throw new DomainException('libsodium is not available');
}
+ if (!\is_string($key)) {
+ throw new InvalidArgumentException('key must be a string when using EdDSA');
+ }
try {
// The last non-empty line is used as the key.
$lines = array_filter(explode("\n", $key));
- $key = base64_decode(end($lines));
+ $key = base64_decode((string) end($lines));
+ if (\strlen($key) === 0) {
+ throw new DomainException('Key cannot be empty string');
+ }
return sodium_crypto_sign_detached($msg, $key);
} catch (Exception $e) {
throw new DomainException($e->getMessage(), 0, $e);
}
}
+
+ throw new DomainException('Algorithm not supported');
}
/**
* Verify a signature with the message, key and method. Not all methods
* are symmetric, so we must have a separate verify and sign method.
*
- * @param string $msg The original message (header and body)
- * @param string $signature The original signature
- * @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key
- * @param string $alg The algorithm
+ * @param string $msg The original message (header and body)
+ * @param string $signature The original signature
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial For HS*, a string key works. for RS*, must be an instance of OpenSSLAsymmetricKey
+ * @param string $alg The algorithm
*
* @return bool
*
* @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure
*/
- private static function verify($msg, $signature, $key, $alg)
- {
+ private static function verify(
+ string $msg,
+ string $signature,
+ $keyMaterial,
+ string $alg
+ ): bool {
if (empty(static::$supported_algs[$alg])) {
throw new DomainException('Algorithm not supported');
}
@@ -269,10 +298,11 @@ class JWT
list($function, $algorithm) = static::$supported_algs[$alg];
switch ($function) {
case 'openssl':
- $success = \openssl_verify($msg, $signature, $key, $algorithm);
+ $success = \openssl_verify($msg, $signature, $keyMaterial, $algorithm); // @phpstan-ignore-line
if ($success === 1) {
return true;
- } elseif ($success === 0) {
+ }
+ if ($success === 0) {
return false;
}
// returns 1 on success, 0 on failure, -1 on error.
@@ -280,21 +310,33 @@ class JWT
'OpenSSL error: ' . \openssl_error_string()
);
case 'sodium_crypto':
- if (!function_exists('sodium_crypto_sign_verify_detached')) {
- throw new DomainException('libsodium is not available');
- }
- try {
- // The last non-empty line is used as the key.
- $lines = array_filter(explode("\n", $key));
- $key = base64_decode(end($lines));
- return sodium_crypto_sign_verify_detached($signature, $msg, $key);
- } catch (Exception $e) {
- throw new DomainException($e->getMessage(), 0, $e);
- }
+ if (!\function_exists('sodium_crypto_sign_verify_detached')) {
+ throw new DomainException('libsodium is not available');
+ }
+ if (!\is_string($keyMaterial)) {
+ throw new InvalidArgumentException('key must be a string when using EdDSA');
+ }
+ try {
+ // The last non-empty line is used as the key.
+ $lines = array_filter(explode("\n", $keyMaterial));
+ $key = base64_decode((string) end($lines));
+ if (\strlen($key) === 0) {
+ throw new DomainException('Key cannot be empty string');
+ }
+ if (\strlen($signature) === 0) {
+ throw new DomainException('Signature cannot be empty string');
+ }
+ return sodium_crypto_sign_verify_detached($signature, $msg, $key);
+ } catch (Exception $e) {
+ throw new DomainException($e->getMessage(), 0, $e);
+ }
case 'hash_hmac':
default:
- $hash = \hash_hmac($algorithm, $msg, $key, true);
- return self::constantTimeEquals($signature, $hash);
+ if (!\is_string($keyMaterial)) {
+ throw new InvalidArgumentException('key must be a string when using hmac');
+ }
+ $hash = \hash_hmac($algorithm, $msg, $keyMaterial, true);
+ return self::constantTimeEquals($hash, $signature);
}
}
@@ -303,30 +345,16 @@ class JWT
*
* @param string $input JSON string
*
- * @return object Object representation of JSON string
+ * @return mixed The decoded JSON string
*
* @throws DomainException Provided string was invalid JSON
*/
- public static function jsonDecode($input)
+ public static function jsonDecode(string $input)
{
- if (\version_compare(PHP_VERSION, '5.4.0', '>=') && !(\defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
- /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
- * to specify that large ints (like Steam Transaction IDs) should be treated as
- * strings, rather than the PHP default behaviour of converting them to floats.
- */
- $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
- } else {
- /** Not all servers will support that, however, so for older versions we must
- * manually detect large ints in the JSON string and quote them (thus converting
- *them to strings) before decoding, hence the preg_replace() call.
- */
- $max_int_length = \strlen((string) PHP_INT_MAX) - 1;
- $json_without_bigints = \preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
- $obj = \json_decode($json_without_bigints);
- }
+ $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
if ($errno = \json_last_error()) {
- static::handleJsonError($errno);
+ self::handleJsonError($errno);
} elseif ($obj === null && $input !== 'null') {
throw new DomainException('Null result with non-null input');
}
@@ -334,22 +362,30 @@ class JWT
}
/**
- * Encode a PHP object into a JSON string.
+ * Encode a PHP array into a JSON string.
*
- * @param object|array $input A PHP object or array
+ * @param array<mixed> $input A PHP array
*
- * @return string JSON representation of the PHP object or array
+ * @return string JSON representation of the PHP array
*
* @throws DomainException Provided object could not be encoded to valid JSON
*/
- public static function jsonEncode($input)
+ public static function jsonEncode(array $input): string
{
- $json = \json_encode($input);
+ if (PHP_VERSION_ID >= 50400) {
+ $json = \json_encode($input, \JSON_UNESCAPED_SLASHES);
+ } else {
+ // PHP 5.3 only
+ $json = \json_encode($input);
+ }
if ($errno = \json_last_error()) {
- static::handleJsonError($errno);
- } elseif ($json === 'null' && $input !== null) {
+ self::handleJsonError($errno);
+ } elseif ($json === 'null') {
throw new DomainException('Null result with non-null input');
}
+ if ($json === false) {
+ throw new DomainException('Provided object could not be encoded to valid JSON');
+ }
return $json;
}
@@ -359,8 +395,10 @@ class JWT
* @param string $input A Base64 encoded string
*
* @return string A decoded string
+ *
+ * @throws InvalidArgumentException invalid base64 characters
*/
- public static function urlsafeB64Decode($input)
+ public static function urlsafeB64Decode(string $input): string
{
$remainder = \strlen($input) % 4;
if ($remainder) {
@@ -377,7 +415,7 @@ class JWT
*
* @return string The base64 encode of what you passed in
*/
- public static function urlsafeB64Encode($input)
+ public static function urlsafeB64Encode(string $input): string
{
return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
}
@@ -386,67 +424,54 @@ class JWT
/**
* Determine if an algorithm has been provided for each Key
*
- * @param Key|array<Key>|mixed $keyOrKeyArray
- * @param string|null $kid
+ * @param Key|ArrayAccess<string,Key>|array<string,Key> $keyOrKeyArray
+ * @param string|null $kid
*
* @throws UnexpectedValueException
*
- * @return array containing the keyMaterial and algorithm
+ * @return Key
*/
- private static function getKeyMaterialAndAlgorithm($keyOrKeyArray, $kid = null)
- {
- if (
- is_string($keyOrKeyArray)
- || is_resource($keyOrKeyArray)
- || $keyOrKeyArray instanceof OpenSSLAsymmetricKey
- ) {
- return array($keyOrKeyArray, null);
- }
-
+ private static function getKey(
+ $keyOrKeyArray,
+ ?string $kid
+ ): Key {
if ($keyOrKeyArray instanceof Key) {
- return array($keyOrKeyArray->getKeyMaterial(), $keyOrKeyArray->getAlgorithm());
+ return $keyOrKeyArray;
}
- if (is_array($keyOrKeyArray) || $keyOrKeyArray instanceof ArrayAccess) {
- if (!isset($kid)) {
- throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
- }
- if (!isset($keyOrKeyArray[$kid])) {
- throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
- }
-
- $key = $keyOrKeyArray[$kid];
+ if (empty($kid) && $kid !== '0') {
+ throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
+ }
- if ($key instanceof Key) {
- return array($key->getKeyMaterial(), $key->getAlgorithm());
- }
+ if ($keyOrKeyArray instanceof CachedKeySet) {
+ // Skip "isset" check, as this will automatically refresh if not set
+ return $keyOrKeyArray[$kid];
+ }
- return array($key, null);
+ if (!isset($keyOrKeyArray[$kid])) {
+ throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
}
- throw new UnexpectedValueException(
- '$keyOrKeyArray must be a string|resource key, an array of string|resource keys, '
- . 'an instance of Firebase\JWT\Key key or an array of Firebase\JWT\Key keys'
- );
+ return $keyOrKeyArray[$kid];
}
/**
- * @param string $left
- * @param string $right
+ * @param string $left The string of known length to compare against
+ * @param string $right The user-supplied string
* @return bool
*/
- public static function constantTimeEquals($left, $right)
+ public static function constantTimeEquals(string $left, string $right): bool
{
if (\function_exists('hash_equals')) {
return \hash_equals($left, $right);
}
- $len = \min(static::safeStrlen($left), static::safeStrlen($right));
+ $len = \min(self::safeStrlen($left), self::safeStrlen($right));
$status = 0;
for ($i = 0; $i < $len; $i++) {
$status |= (\ord($left[$i]) ^ \ord($right[$i]));
}
- $status |= (static::safeStrlen($left) ^ static::safeStrlen($right));
+ $status |= (self::safeStrlen($left) ^ self::safeStrlen($right));
return ($status === 0);
}
@@ -456,17 +481,19 @@ class JWT
*
* @param int $errno An error number from json_last_error()
*
+ * @throws DomainException
+ *
* @return void
*/
- private static function handleJsonError($errno)
+ private static function handleJsonError(int $errno): void
{
- $messages = array(
+ $messages = [
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3
- );
+ ];
throw new DomainException(
isset($messages[$errno])
? $messages[$errno]
@@ -481,7 +508,7 @@ class JWT
*
* @return int
*/
- private static function safeStrlen($str)
+ private static function safeStrlen(string $str): int
{
if (\function_exists('mb_strlen')) {
return \mb_strlen($str, '8bit');
@@ -495,10 +522,11 @@ class JWT
* @param string $sig The ECDSA signature to convert
* @return string The encoded DER object
*/
- private static function signatureToDER($sig)
+ private static function signatureToDER(string $sig): string
{
// Separate the signature into r-value and s-value
- list($r, $s) = \str_split($sig, (int) (\strlen($sig) / 2));
+ $length = max(1, (int) (\strlen($sig) / 2));
+ list($r, $s) = \str_split($sig, $length);
// Trim leading zeros
$r = \ltrim($r, "\x00");
@@ -525,9 +553,10 @@ class JWT
*
* @param int $type DER tag
* @param string $value the value to encode
+ *
* @return string the encoded object
*/
- private static function encodeDER($type, $value)
+ private static function encodeDER(int $type, string $value): string
{
$tag_header = 0;
if ($type === self::ASN1_SEQUENCE) {
@@ -548,9 +577,10 @@ class JWT
*
* @param string $der binary signature in DER format
* @param int $keySize the number of bits in the key
+ *
* @return string the signature
*/
- private static function signatureFromDER($der, $keySize)
+ private static function signatureFromDER(string $der, int $keySize): string
{
// OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
list($offset, $_) = self::readDER($der);
@@ -575,9 +605,10 @@ class JWT
* @param string $der the binary data in DER format
* @param int $offset the offset of the data stream containing the object
* to decode
- * @return array [$offset, $data] the new offset and the decoded object
+ *
+ * @return array{int, string|null} the new offset and the decoded object
*/
- private static function readDER($der, $offset = 0)
+ private static function readDER(string $der, int $offset = 0): array
{
$pos = $offset;
$size = \strlen($der);
@@ -595,7 +626,7 @@ class JWT
}
// Value
- if ($type == self::ASN1_BIT_STRING) {
+ if ($type === self::ASN1_BIT_STRING) {
$pos++; // Skip the first contents octet (padding indicator)
$data = \substr($der, $pos, $len - 1);
$pos += $len - 1;
@@ -606,6 +637,6 @@ class JWT
$data = null;
}
- return array($pos, $data);
+ return [$pos, $data];
}
}
diff --git a/data/web/inc/lib/vendor/firebase/php-jwt/src/Key.php b/data/web/inc/lib/vendor/firebase/php-jwt/src/Key.php
index f1ede6f2..00cf7f2e 100644
--- a/data/web/inc/lib/vendor/firebase/php-jwt/src/Key.php
+++ b/data/web/inc/lib/vendor/firebase/php-jwt/src/Key.php
@@ -4,37 +4,42 @@ namespace Firebase\JWT;
use InvalidArgumentException;
use OpenSSLAsymmetricKey;
+use OpenSSLCertificate;
+use TypeError;
class Key
{
- /** @var string $algorithm */
- private $algorithm;
-
- /** @var string|resource|OpenSSLAsymmetricKey $keyMaterial */
+ /** @var string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate */
private $keyMaterial;
+ /** @var string */
+ private $algorithm;
/**
- * @param string|resource|OpenSSLAsymmetricKey $keyMaterial
+ * @param string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial
* @param string $algorithm
*/
- public function __construct($keyMaterial, $algorithm)
- {
+ public function __construct(
+ $keyMaterial,
+ string $algorithm
+ ) {
if (
- !is_string($keyMaterial)
- && !is_resource($keyMaterial)
+ !\is_string($keyMaterial)
&& !$keyMaterial instanceof OpenSSLAsymmetricKey
+ && !$keyMaterial instanceof OpenSSLCertificate
+ && !\is_resource($keyMaterial)
) {
- throw new InvalidArgumentException('Type error: $keyMaterial must be a string, resource, or OpenSSLAsymmetricKey');
+ throw new TypeError('Key material must be a string, resource, or OpenSSLAsymmetricKey');
}
if (empty($keyMaterial)) {
- throw new InvalidArgumentException('Type error: $keyMaterial must not be empty');
+ throw new InvalidArgumentException('Key material must not be empty');
}
- if (!is_string($algorithm)|| empty($keyMaterial)) {
- throw new InvalidArgumentException('Type error: $algorithm must be a string');
+ if (empty($algorithm)) {
+ throw new InvalidArgumentException('Algorithm must not be empty');
}
+ // TODO: Remove in PHP 8.0 in favor of class constructor property promotion
$this->keyMaterial = $keyMaterial;
$this->algorithm = $algorithm;
}
@@ -44,13 +49,13 @@ class Key
*
* @return string
*/
- public function getAlgorithm()
+ public function getAlgorithm(): string
{
return $this->algorithm;
}
/**
- * @return string|resource|OpenSSLAsymmetricKey
+ * @return string|resource|OpenSSLAsymmetricKey|OpenSSLCertificate
*/
public function getKeyMaterial()
{
diff --git a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.travis.yml b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.travis.yml
index 87831a56..c5f3825a 100644
--- a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.travis.yml
+++ b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.travis.yml
@@ -3,9 +3,12 @@ language: php
sudo: false
php:
- - 5.6
- - 7.0
- - 7.1
+ - 7.2
+ - 7.3
+ - 7.4
+ - 8.0
+ - 8.1
+ - 8.2
matrix:
include:
diff --git a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/README.md b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/README.md
index e050a6d0..d0b1acaf 100644
--- a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/README.md
+++ b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/README.md
@@ -36,6 +36,7 @@ $provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
'encryptionAlgorithm' => 'RS256', // optional
'encryptionKeyPath' => '../key.pem' // optional
'encryptionKey' => 'contents_of_key_or_certificate' // optional
+ 'version' => '20.0.1', // optional
]);
if (!isset($_GET['code'])) {
diff --git a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/composer.json b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/composer.json
index 958f8c3a..b6a54477 100644
--- a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/composer.json
+++ b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/composer.json
@@ -18,13 +18,14 @@
"keycloak"
],
"require": {
+ "php": "~7.2 || ~8.0",
"league/oauth2-client": "^2.0",
- "firebase/php-jwt": "~4.0|~5.0"
+ "firebase/php-jwt": "^4.0 || ^5.0 || ^6.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.0",
- "mockery/mockery": "~0.9",
- "squizlabs/php_codesniffer": "~2.0"
+ "phpunit/phpunit": "~9.6.4",
+ "mockery/mockery": "~1.5.0",
+ "squizlabs/php_codesniffer": "~3.7.0"
},
"autoload": {
"psr-4": {
@@ -40,5 +41,11 @@
"branch-alias": {
"dev-master": "1.0.x-dev"
}
+ },
+ "scripts": {
+ "test": [
+ "@putenv XDEBUG_MODE=coverage",
+ "phpunit --colors=always"
+ ]
}
-}
+}
\ No newline at end of file
diff --git a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/phpunit.xml.dist b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/phpunit.xml.dist
index 04d164dc..b915f933 100644
--- a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/phpunit.xml.dist
+++ b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/phpunit.xml.dist
@@ -1,38 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
- backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
- convertErrorsToExceptions="true"
- convertNoticesToExceptions="true"
- convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
- syntaxCheck="false"
+ failOnRisky="true"
+ failOnWarning="true"
>
- <logging>
- <log type="coverage-html"
- target="./build/coverage/html"
- charset="UTF-8"
- highlight="false"
- lowUpperBound="35"
- highLowerBound="70"/>
- <log type="coverage-clover"
- target="./build/coverage/log/coverage.xml"/>
- </logging>
+ <coverage includeUncoveredFiles="true"
+ pathCoverage="false"
+ ignoreDeprecatedCodeUnits="true"
+ disableCodeCoverageIgnore="true">
+ <include>
+ <directory suffix=".php">src</directory>
+ </include>
+ <exclude>
+ <directory suffix=".php">vendor</directory>
+ <file>src/autoload.php</file>
+ </exclude>
+ <report>
+ <html outputDirectory="./build/coverage/html"
+ lowUpperBound="35"
+ highLowerBound="70"/>
+ <clover outputFile="./build/coverage/log/coverage.xml"/>
+ </report>
+ </coverage>
<testsuites>
<testsuite name="Package Test Suite">
<directory suffix=".php">./test/</directory>
</testsuite>
</testsuites>
- <filter>
- <whitelist>
- <directory suffix=".php">./</directory>
- <exclude>
- <directory suffix=".php">./examples</directory>
- <directory suffix=".php">./vendor</directory>
- <directory suffix=".php">./test</directory>
- </exclude>
- </whitelist>
- </filter>
</phpunit>
diff --git a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/test/src/Provider/KeycloakTest.php b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/test/src/Provider/KeycloakTest.php
index 01f6b62d..a5c1da14 100644
--- a/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/test/src/Provider/KeycloakTest.php
+++ b/data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/test/src/Provider/KeycloakTest.php
@@ -23,18 +23,22 @@ namespace Stevenmaguire\OAuth2\Client\Provider
namespace Stevenmaguire\OAuth2\Client\Test\Provider
{
+ use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Tool\QueryBuilderTrait;
use Mockery as m;
+ use PHPUnit\Framework\TestCase;
+ use Stevenmaguire\OAuth2\Client\Provider\Exception\EncryptionConfigurationException;
+ use Stevenmaguire\OAuth2\Client\Provider\Keycloak;
- class KeycloakTest extends \PHPUnit_Framework_TestCase
+ class KeycloakTest extends TestCase
{
use QueryBuilderTrait;
protected $provider;
- protected function setUp()
+ protected function setUp(): void
{
- $this->provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
+ $this->provider = new Keycloak([
'authServerUrl' => 'http://mock.url/auth',
'realm' => 'mock_realm',
'clientId' => 'mock_client_id',
@@ -43,7 +47,7 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
]);
}
- public function tearDown()
+ public function tearDown(): void
{
m::close();
parent::tearDown();
@@ -67,7 +71,7 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
public function testEncryptionAlgorithm()
{
$algorithm = uniqid();
- $provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
+ $provider = new Keycloak([
'encryptionAlgorithm' => $algorithm,
]);
@@ -82,7 +86,7 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
public function testEncryptionKey()
{
$key = uniqid();
- $provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
+ $provider = new Keycloak([
'encryptionKey' => $key,
]);
@@ -101,7 +105,7 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
$key = uniqid();
$mockFileGetContents = $key;
- $provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
+ $provider = new Keycloak([
'encryptionKeyPath' => $path,
]);
@@ -118,12 +122,14 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
public function testEncryptionKeyPathFails()
{
+ $this->markTestIncomplete('Need to assess the test to see what is required to be checked.');
+
global $mockFileGetContents;
$path = uniqid();
$key = uniqid();
$mockFileGetContents = new \Exception();
- $provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
+ $provider = new Keycloak([
'encryptionKeyPath' => $path,
]);
@@ -137,7 +143,7 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
$query = ['scope' => implode($scopeSeparator, $options['scope'])];
$url = $this->provider->getAuthorizationUrl($options);
$encodedScope = $this->buildQueryString($query);
- $this->assertContains($encodedScope, $url);
+ $this->assertStringContainsString($encodedScope, $url);
}
public function testGetAuthorizationUrl()
@@ -169,11 +175,15 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
public function testGetAccessToken()
{
$response = m::mock('Psr\Http\Message\ResponseInterface');
- $response->shouldReceive('getBody')->andReturn('{"access_token":"mock_access_token", "scope":"email", "token_type":"bearer"}');
- $response->shouldReceive('getHeader')->andReturn(['content-type' => 'json']);
+ $response->shouldReceive('getBody')
+ ->andReturn('{"access_token":"mock_access_token", "scope":"email", "token_type":"bearer"}');
+ $response->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'json']);
$client = m::mock('GuzzleHttp\ClientInterface');
- $client->shouldReceive('send')->times(1)->andReturn($response);
+ $client->shouldReceive('send')
+ ->times(1)
+ ->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
@@ -186,18 +196,24 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
public function testUserData()
{
- $userId = rand(1000,9999);
+ $userId = rand(1000, 9999);
$name = uniqid();
$nickname = uniqid();
$email = uniqid();
$postResponse = m::mock('Psr\Http\Message\ResponseInterface');
- $postResponse->shouldReceive('getBody')->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
- $postResponse->shouldReceive('getHeader')->andReturn(['content-type' => 'application/x-www-form-urlencoded']);
+ $postResponse->shouldReceive('getBody')
+ ->andReturn(
+ 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}'
+ );
+ $postResponse->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'application/x-www-form-urlencoded']);
$userResponse = m::mock('Psr\Http\Message\ResponseInterface');
- $userResponse->shouldReceive('getBody')->andReturn('{"sub": '.$userId.', "name": "'.$name.'", "email": "'.$email.'"}');
- $userResponse->shouldReceive('getHeader')->andReturn(['content-type' => 'json']);
+ $userResponse->shouldReceive('getBody')
+ ->andReturn('{"sub": '.$userId.', "name": "'.$name.'", "email": "'.$email.'"}');
+ $userResponse->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'json']);
$client = m::mock('GuzzleHttp\ClientInterface');
$client->shouldReceive('send')
@@ -218,7 +234,7 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
public function testUserDataWithEncryption()
{
- $userId = rand(1000,9999);
+ $userId = rand(1000, 9999);
$name = uniqid();
$nickname = uniqid();
$email = uniqid();
@@ -227,21 +243,31 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
$key = uniqid();
$postResponse = m::mock('Psr\Http\Message\ResponseInterface');
- $postResponse->shouldReceive('getBody')->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
- $postResponse->shouldReceive('getHeader')->andReturn(['content-type' => 'application/x-www-form-urlencoded']);
- $postResponse->shouldReceive('getStatusCode')->andReturn(200);
+ $postResponse->shouldReceive('getBody')
+ ->andReturn(
+ 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}'
+ );
+ $postResponse->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'application/x-www-form-urlencoded']);
+ $postResponse->shouldReceive('getStatusCode')
+ ->andReturn(200);
$userResponse = m::mock('Psr\Http\Message\ResponseInterface');
- $userResponse->shouldReceive('getBody')->andReturn($jwt);
- $userResponse->shouldReceive('getHeader')->andReturn(['content-type' => 'application/jwt']);
- $userResponse->shouldReceive('getStatusCode')->andReturn(200);
+ $userResponse->shouldReceive('getBody')
+ ->andReturn($jwt);
+ $userResponse->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'application/jwt']);
+ $userResponse->shouldReceive('getStatusCode')
+ ->andReturn(200);
$decoder = \Mockery::mock('overload:Firebase\JWT\JWT');
- $decoder->shouldReceive('decode')->with($jwt, $key, [$algorithm])->andReturn([
- 'sub' => $userId,
- 'email' => $email,
- 'name' => $name,
- ]);
+ $decoder->shouldReceive('decode')
+ ->with($jwt, $key, [$algorithm])
+ ->andReturn([
+ 'sub' => $userId,
+ 'email' => $email,
+ 'name' => $name,
+ ]);
$client = m::mock('GuzzleHttp\ClientInterface');
$client->shouldReceive('send')
@@ -262,20 +288,27 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
$this->assertEquals($email, $user->toArray()['email']);
}
- /**
- * @expectedException Stevenmaguire\OAuth2\Client\Provider\Exception\EncryptionConfigurationException
- */
public function testUserDataFailsWhenEncryptionEncounteredAndNotConfigured()
{
+ $this->expectException(EncryptionConfigurationException::class);
+
$postResponse = m::mock('Psr\Http\Message\ResponseInterface');
- $postResponse->shouldReceive('getBody')->andReturn('access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}');
- $postResponse->shouldReceive('getHeader')->andReturn(['content-type' => 'application/x-www-form-urlencoded']);
- $postResponse->shouldReceive('getStatusCode')->andReturn(200);
+ $postResponse->shouldReceive('getBody')
+ ->andReturn(
+ 'access_token=mock_access_token&expires=3600&refresh_token=mock_refresh_token&otherKey={1234}'
+ );
+ $postResponse->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'application/x-www-form-urlencoded']);
+ $postResponse->shouldReceive('getStatusCode')
+ ->andReturn(200);
$userResponse = m::mock('Psr\Http\Message\ResponseInterface');
- $userResponse->shouldReceive('getBody')->andReturn(uniqid());
- $userResponse->shouldReceive('getHeader')->andReturn(['content-type' => 'application/jwt']);
- $userResponse->shouldReceive('getStatusCode')->andReturn(200);
+ $userResponse->shouldReceive('getBody')
+ ->andReturn(uniqid());
+ $userResponse->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'application/jwt']);
+ $userResponse->shouldReceive('getStatusCode')
+ ->andReturn(200);
$client = m::mock('GuzzleHttp\ClientInterface');
$client->shouldReceive('send')
@@ -287,17 +320,20 @@ namespace Stevenmaguire\OAuth2\Client\Test\Provider
$user = $this->provider->getResourceOwner($token);
}
- /**
- * @expectedException League\OAuth2\Client\Provider\Exception\IdentityProviderException
- */
public function testErrorResponse()
{
+ $this->expectException(IdentityProviderException::class);
+
$response = m::mock('Psr\Http\Message\ResponseInterface');
- $response->shouldReceive('getBody')->andReturn('{"error": "invalid_grant", "error_description": "Code not found"}');
- $response->shouldReceive('getHeader')->andReturn(['content-type' => 'json']);
+ $response->shouldReceive('getBody')
+ ->andReturn('{"error": "invalid_grant", "error_description": "Code not found"}');
+ $response->shouldReceive('getHeader')
+ ->andReturn(['content-type' => 'json']);
$client = m::mock('GuzzleHttp\ClientInterface');
- $client->shouldReceive('send')->times(1)->andReturn($response);
+ $client->shouldReceive('send')
+ ->times(1)
+ ->andReturn($response);
$this->provider->setHttpClient($client);
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);