[Web] add oauth2-keycloak lib
This commit is contained in:
4
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.gitignore
vendored
Normal file
4
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/build
|
||||
/vendor
|
||||
composer.phar
|
||||
composer.lock
|
35
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.scrutinizer.yml
vendored
Normal file
35
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.scrutinizer.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
filter:
|
||||
excluded_paths: [test/*]
|
||||
checks:
|
||||
php:
|
||||
code_rating: true
|
||||
remove_extra_empty_lines: true
|
||||
remove_php_closing_tag: true
|
||||
remove_trailing_whitespace: true
|
||||
fix_use_statements:
|
||||
remove_unused: true
|
||||
preserve_multiple: false
|
||||
preserve_blanklines: true
|
||||
order_alphabetically: true
|
||||
fix_php_opening_tag: true
|
||||
fix_linefeed: true
|
||||
fix_line_ending: true
|
||||
fix_identation_4spaces: true
|
||||
fix_doc_comments: true
|
||||
tools:
|
||||
external_code_coverage:
|
||||
timeout: 600
|
||||
runs: 2
|
||||
php_analyzer: true
|
||||
php_code_coverage: false
|
||||
php_code_sniffer:
|
||||
config:
|
||||
standard: PSR2
|
||||
filter:
|
||||
paths: ['src']
|
||||
php_loc:
|
||||
enabled: true
|
||||
excluded_dirs: [examples, vendor, test]
|
||||
php_cpd:
|
||||
enabled: true
|
||||
excluded_dirs: [examples, vendor, test]
|
26
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.travis.yml
vendored
Normal file
26
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/.travis.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.6
|
||||
env: 'COMPOSER_FLAGS="--prefer-stable --prefer-lowest"'
|
||||
|
||||
before_script:
|
||||
- travis_retry composer self-update
|
||||
- travis_retry composer install --no-interaction --prefer-source --dev
|
||||
- travis_retry phpenv rehash
|
||||
|
||||
script:
|
||||
- ./vendor/bin/phpcs --standard=psr2 src/
|
||||
- ./vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
|
||||
|
||||
after_script:
|
||||
- wget https://scrutinizer-ci.com/ocular.phar
|
||||
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
|
74
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/CHANGELOG.md
vendored
Normal file
74
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# Changelog
|
||||
All Notable changes to `oauth2-keycloak` will be documented in this file
|
||||
|
||||
## 2.1.0 - 2018-03-12
|
||||
|
||||
### Added
|
||||
- Introduce `getLogoutUrl` method on provider to build and return and authorized logout url - thanks @FlxPeters
|
||||
|
||||
### Deprecated
|
||||
- Nothing
|
||||
|
||||
### Fixed
|
||||
- Nothing
|
||||
|
||||
### Removed
|
||||
- Nothing
|
||||
|
||||
### Security
|
||||
- Nothing
|
||||
|
||||
## 2.0.0 - 2017-01-25
|
||||
|
||||
### Added
|
||||
- PHP 7.1 Support
|
||||
|
||||
### Deprecated
|
||||
- Nothing
|
||||
|
||||
### Fixed
|
||||
- Nothing
|
||||
|
||||
### Removed
|
||||
- PHP 5.5 Support
|
||||
|
||||
### Security
|
||||
- Nothing
|
||||
|
||||
## 1.0.0 - 2017-01-25
|
||||
|
||||
Bump for base package parity
|
||||
|
||||
## 0.2.0 - 2016-12-07
|
||||
|
||||
### Added
|
||||
- JSON Web Token decryption support
|
||||
|
||||
### Deprecated
|
||||
- Nothing
|
||||
|
||||
### Fixed
|
||||
- Nothing
|
||||
|
||||
### Removed
|
||||
- Nothing
|
||||
|
||||
### Security
|
||||
- Nothing
|
||||
|
||||
## 0.1.0 - 2015-08-31
|
||||
|
||||
### Added
|
||||
- Initial release!
|
||||
|
||||
### Deprecated
|
||||
- Nothing
|
||||
|
||||
### Fixed
|
||||
- Nothing
|
||||
|
||||
### Removed
|
||||
- Nothing
|
||||
|
||||
### Security
|
||||
- Nothing
|
42
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/CONTRIBUTING.md
vendored
Normal file
42
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# Contributing
|
||||
|
||||
Contributions are **welcome** and will be fully **credited**.
|
||||
|
||||
We accept contributions via Pull Requests on [Github](https://github.com/stevenmaguire/oauth2-keycloak).
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
|
||||
|
||||
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
|
||||
|
||||
- **Document any change in behaviour** - Make sure the README and any other relevant documentation are kept up-to-date.
|
||||
|
||||
- **Consider our release cycle** - We try to follow SemVer. Randomly breaking public APIs is not an option.
|
||||
|
||||
- **Create topic branches** - Don't ask us to pull from your master branch.
|
||||
|
||||
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
|
||||
|
||||
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
|
||||
|
||||
- **Ensure tests pass!** - Please run the tests (see below) before submitting your pull request, and make sure they pass. We won't accept a patch until all tests pass.
|
||||
|
||||
- **Ensure no coding standards violations** - Please run PHP Code Sniffer using the PSR-2 standard (see below) before submitting your pull request. A violation will cause the build to fail, so please make sure there are no violations. We can't accept a patch if the build fails.
|
||||
|
||||
|
||||
## Running Tests
|
||||
|
||||
``` bash
|
||||
$ ./vendor/bin/phpunit
|
||||
```
|
||||
|
||||
|
||||
## Running PHP Code Sniffer
|
||||
|
||||
``` bash
|
||||
$ ./vendor/bin/phpcs src --standard=psr2 -sp
|
||||
```
|
||||
|
||||
**Happy coding**!
|
21
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/LICENSE
vendored
Normal file
21
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Steven Maguire
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
175
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/README.md
vendored
Normal file
175
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/README.md
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
# Keycloak Provider for OAuth 2.0 Client
|
||||
[](https://github.com/stevenmaguire/oauth2-keycloak/releases)
|
||||
[](LICENSE.md)
|
||||
[](https://travis-ci.org/stevenmaguire/oauth2-keycloak)
|
||||
[](https://scrutinizer-ci.com/g/stevenmaguire/oauth2-keycloak/code-structure)
|
||||
[](https://scrutinizer-ci.com/g/stevenmaguire/oauth2-keycloak)
|
||||
[](https://packagist.org/packages/stevenmaguire/oauth2-keycloak)
|
||||
|
||||
This package provides Keycloak OAuth 2.0 support for the PHP League's [OAuth 2.0 Client](https://github.com/thephpleague/oauth2-client).
|
||||
|
||||
## Installation
|
||||
|
||||
To install, use composer:
|
||||
|
||||
```
|
||||
composer require stevenmaguire/oauth2-keycloak
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Usage is the same as The League's OAuth client, using `\Stevenmaguire\OAuth2\Client\Provider\Keycloak` as the provider.
|
||||
|
||||
Use `authServerUrl` to specify the Keycloak server URL. You can lookup the correct value from the Keycloak client installer JSON under `auth-server-url`, eg. `http://localhost:8080/auth`.
|
||||
|
||||
Use `realm` to specify the Keycloak realm name. You can lookup the correct value from the Keycloak client installer JSON under `resource`, eg. `master`.
|
||||
|
||||
### Authorization Code Flow
|
||||
|
||||
```php
|
||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'authServerUrl' => '{keycloak-server-url}',
|
||||
'realm' => '{keycloak-realm}',
|
||||
'clientId' => '{keycloak-client-id}',
|
||||
'clientSecret' => '{keycloak-client-secret}',
|
||||
'redirectUri' => 'https://example.com/callback-url',
|
||||
'encryptionAlgorithm' => 'RS256', // optional
|
||||
'encryptionKeyPath' => '../key.pem' // optional
|
||||
'encryptionKey' => 'contents_of_key_or_certificate' // optional
|
||||
]);
|
||||
|
||||
if (!isset($_GET['code'])) {
|
||||
|
||||
// If we don't have an authorization code then get one
|
||||
$authUrl = $provider->getAuthorizationUrl();
|
||||
$_SESSION['oauth2state'] = $provider->getState();
|
||||
header('Location: '.$authUrl);
|
||||
exit;
|
||||
|
||||
// Check given state against previously stored one to mitigate CSRF attack
|
||||
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
|
||||
|
||||
unset($_SESSION['oauth2state']);
|
||||
exit('Invalid state, make sure HTTP sessions are enabled.');
|
||||
|
||||
} else {
|
||||
|
||||
// Try to get an access token (using the authorization coe grant)
|
||||
try {
|
||||
$token = $provider->getAccessToken('authorization_code', [
|
||||
'code' => $_GET['code']
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
exit('Failed to get access token: '.$e->getMessage());
|
||||
}
|
||||
|
||||
// Optional: Now you have a token you can look up a users profile data
|
||||
try {
|
||||
|
||||
// We got an access token, let's now get the user's details
|
||||
$user = $provider->getResourceOwner($token);
|
||||
|
||||
// Use these details to create a new profile
|
||||
printf('Hello %s!', $user->getName());
|
||||
|
||||
} catch (Exception $e) {
|
||||
exit('Failed to get resource owner: '.$e->getMessage());
|
||||
}
|
||||
|
||||
// Use this to interact with an API on the users behalf
|
||||
echo $token->getToken();
|
||||
}
|
||||
```
|
||||
|
||||
### Refreshing a Token
|
||||
|
||||
```php
|
||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'authServerUrl' => '{keycloak-server-url}',
|
||||
'realm' => '{keycloak-realm}',
|
||||
'clientId' => '{keycloak-client-id}',
|
||||
'clientSecret' => '{keycloak-client-secret}',
|
||||
'redirectUri' => 'https://example.com/callback-url',
|
||||
]);
|
||||
|
||||
$token = $provider->getAccessToken('refresh_token', ['refresh_token' => $token->getRefreshToken()]);
|
||||
```
|
||||
|
||||
### Handling encryption
|
||||
|
||||
If you've configured your Keycloak instance to use encryption, there are some advanced options available to you.
|
||||
|
||||
#### Configure the provider to use the same encryption algorithm
|
||||
|
||||
```php
|
||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
// ...
|
||||
'encryptionAlgorithm' => 'RS256',
|
||||
]);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```php
|
||||
$provider->setEncryptionAlgorithm('RS256');
|
||||
```
|
||||
|
||||
#### Configure the provider to use the expected decryption public key or certificate
|
||||
|
||||
##### By key value
|
||||
|
||||
```php
|
||||
$key = "-----BEGIN PUBLIC KEY-----\n....\n-----END PUBLIC KEY-----";
|
||||
// or
|
||||
// $key = "-----BEGIN CERTIFICATE-----\n....\n-----END CERTIFICATE-----";
|
||||
|
||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
// ...
|
||||
'encryptionKey' => $key,
|
||||
]);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```php
|
||||
$provider->setEncryptionKey($key);
|
||||
```
|
||||
|
||||
##### By key path
|
||||
|
||||
```php
|
||||
$keyPath = '../key.pem';
|
||||
|
||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
// ...
|
||||
'encryptionKeyPath' => $keyPath,
|
||||
]);
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```php
|
||||
$provider->setEncryptionKeyPath($keyPath);
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
``` bash
|
||||
$ ./vendor/bin/phpunit
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/stevenmaguire/oauth2-keycloak/blob/master/CONTRIBUTING.md) for details.
|
||||
|
||||
|
||||
## Credits
|
||||
|
||||
- [Steven Maguire](https://github.com/stevenmaguire)
|
||||
- [Martin Stefan](https://github.com/mstefan21)
|
||||
- [All Contributors](https://github.com/stevenmaguire/oauth2-keycloak/contributors)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](https://github.com/stevenmaguire/oauth2-keycloak/blob/master/LICENSE) for more information.
|
44
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/composer.json
vendored
Normal file
44
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/composer.json
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "stevenmaguire/oauth2-keycloak",
|
||||
"description": "Keycloak OAuth 2.0 Client Provider for The PHP League OAuth2-Client",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Steven Maguire",
|
||||
"email": "stevenmaguire@gmail.com",
|
||||
"homepage": "https://github.com/stevenmaguire"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"oauth",
|
||||
"oauth2",
|
||||
"client",
|
||||
"authorization",
|
||||
"authorisation",
|
||||
"keycloak"
|
||||
],
|
||||
"require": {
|
||||
"league/oauth2-client": "^2.0",
|
||||
"firebase/php-jwt": "~4.0|~5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0",
|
||||
"mockery/mockery": "~0.9",
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Stevenmaguire\\OAuth2\\Client\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Stevenmaguire\\OAuth2\\Client\\Test\\": "test/src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
53
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/examples/index.php
vendored
Normal file
53
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/examples/index.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
session_start();
|
||||
|
||||
$provider = new Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'authServerUrl' => '',
|
||||
'realm' => '',
|
||||
'clientId' => '',
|
||||
'clientSecret' => '',
|
||||
'redirectUri' => '',
|
||||
'encryptionAlgorithm' => null,
|
||||
'encryptionKey' => null,
|
||||
'encryptionKeyPath' => null
|
||||
]);
|
||||
|
||||
if (!isset($_GET['code'])) {
|
||||
// If we don't have an authorization code then get one
|
||||
$authUrl = $provider->getAuthorizationUrl();
|
||||
$_SESSION['oauth2state'] = $provider->getState();
|
||||
header('Location: '.$authUrl);
|
||||
exit;
|
||||
|
||||
// Check given state against previously stored one to mitigate CSRF attack
|
||||
} elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {
|
||||
unset($_SESSION['oauth2state']);
|
||||
exit('Invalid state, make sure HTTP sessions are enabled.');
|
||||
} else {
|
||||
// Try to get an access token (using the authorization coe grant)
|
||||
try {
|
||||
$token = $provider->getAccessToken('authorization_code', [
|
||||
'code' => $_GET['code']
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
exit('Failed to get access token: '.$e->getMessage());
|
||||
}
|
||||
|
||||
// Optional: Now you have a token you can look up a users profile data
|
||||
try {
|
||||
|
||||
// We got an access token, let's now get the user's details
|
||||
$user = $provider->getResourceOwner($token);
|
||||
// Use these details to create a new profile
|
||||
printf('Hello %s!\n<br>', $user->getName());
|
||||
|
||||
} catch (Exception $e) {
|
||||
exit('Failed to get resource owner: '.$e->getMessage());
|
||||
}
|
||||
|
||||
// Use this to interact with an API on the users behalf
|
||||
echo $token->getToken();
|
||||
}
|
38
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/phpunit.xml.dist
vendored
Normal file
38
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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"
|
||||
>
|
||||
<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>
|
||||
<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>
|
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Stevenmaguire\OAuth2\Client\Provider\Exception;
|
||||
|
||||
use Exception;
|
||||
|
||||
class EncryptionConfigurationException extends Exception
|
||||
{
|
||||
/**
|
||||
* Returns properly formatted exception when response decryption fails.
|
||||
*
|
||||
* @return \Stevenmaguire\OAuth2\Client\Provider\Exception\EncryptionConfigurationException
|
||||
*/
|
||||
public static function undeterminedEncryption()
|
||||
{
|
||||
return new static(
|
||||
'The given response may be encrypted and sufficient '.
|
||||
'encryption configuration has not been provided.',
|
||||
400
|
||||
);
|
||||
}
|
||||
}
|
387
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/src/Provider/Keycloak.php
vendored
Normal file
387
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/src/Provider/Keycloak.php
vendored
Normal file
@@ -0,0 +1,387 @@
|
||||
<?php
|
||||
|
||||
namespace Stevenmaguire\OAuth2\Client\Provider;
|
||||
|
||||
use Exception;
|
||||
use Firebase\JWT\JWT;
|
||||
use League\OAuth2\Client\Provider\AbstractProvider;
|
||||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||
use League\OAuth2\Client\Token\AccessToken;
|
||||
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Stevenmaguire\OAuth2\Client\Provider\Exception\EncryptionConfigurationException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class Keycloak extends AbstractProvider
|
||||
{
|
||||
use BearerAuthorizationTrait;
|
||||
|
||||
/**
|
||||
* Keycloak URL, eg. http://localhost:8080/auth.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $authServerUrl = null;
|
||||
|
||||
/**
|
||||
* Realm name, eg. demo.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $realm = null;
|
||||
|
||||
/**
|
||||
* Encryption algorithm.
|
||||
*
|
||||
* You must specify supported algorithms for your application. See
|
||||
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
|
||||
* for a list of spec-compliant algorithms.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $encryptionAlgorithm = null;
|
||||
|
||||
/**
|
||||
* Encryption key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $encryptionKey = null;
|
||||
|
||||
/**
|
||||
* Keycloak version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $version = null;
|
||||
|
||||
/**
|
||||
* Constructs an OAuth 2.0 service provider.
|
||||
*
|
||||
* @param array $options An array of options to set on this provider.
|
||||
* Options include `clientId`, `clientSecret`, `redirectUri`, and `state`.
|
||||
* Individual providers may introduce more options, as needed.
|
||||
* @param array $collaborators An array of collaborators that may be used to
|
||||
* override this provider's default behavior. Collaborators include
|
||||
* `grantFactory`, `requestFactory`, `httpClient`, and `randomFactory`.
|
||||
* Individual providers may introduce more collaborators, as needed.
|
||||
*/
|
||||
public function __construct(array $options = [], array $collaborators = [])
|
||||
{
|
||||
if (isset($options['encryptionKeyPath'])) {
|
||||
$this->setEncryptionKeyPath($options['encryptionKeyPath']);
|
||||
unset($options['encryptionKeyPath']);
|
||||
}
|
||||
|
||||
if (isset($options['version'])) {
|
||||
$this->setVersion($options['version']);
|
||||
}
|
||||
|
||||
parent::__construct($options, $collaborators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to decrypt the given response.
|
||||
*
|
||||
* @param string|array|null $response
|
||||
*
|
||||
* @return string|array|null
|
||||
*/
|
||||
public function decryptResponse($response)
|
||||
{
|
||||
if (!is_string($response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
if ($this->usesEncryption()) {
|
||||
return json_decode(
|
||||
json_encode(
|
||||
JWT::decode(
|
||||
$response,
|
||||
$this->encryptionKey,
|
||||
array($this->encryptionAlgorithm)
|
||||
)
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
throw EncryptionConfigurationException::undeterminedEncryption();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authorization url to begin OAuth flow
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseAuthorizationUrl()
|
||||
{
|
||||
return $this->getBaseUrlWithRealm().'/protocol/openid-connect/auth';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get access token url to retrieve token
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseAccessTokenUrl(array $params)
|
||||
{
|
||||
return $this->getBaseUrlWithRealm().'/protocol/openid-connect/token';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get provider url to fetch user details
|
||||
*
|
||||
* @param AccessToken $token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getResourceOwnerDetailsUrl(AccessToken $token)
|
||||
{
|
||||
return $this->getBaseUrlWithRealm().'/protocol/openid-connect/userinfo';
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the logout URL.
|
||||
*
|
||||
* @param array $options
|
||||
* @return string Authorization URL
|
||||
*/
|
||||
public function getLogoutUrl(array $options = [])
|
||||
{
|
||||
$base = $this->getBaseLogoutUrl();
|
||||
$params = $this->getAuthorizationParameters($options);
|
||||
|
||||
// Starting with keycloak 18.0.0, the parameter redirect_uri is no longer supported on logout.
|
||||
// As of this version the parameter is called post_logout_redirect_uri. In addition to this
|
||||
// a parameter id_token_hint has to be provided.
|
||||
if ($this->validateGteVersion('18.0.0')) {
|
||||
if (isset($options['access_token']) === true) {
|
||||
$accessToken = $options['access_token'];
|
||||
|
||||
$params['id_token_hint'] = $accessToken->getValues()['id_token'];
|
||||
$params['post_logout_redirect_uri'] = $params['redirect_uri'];
|
||||
}
|
||||
|
||||
unset($params['redirect_uri']);
|
||||
}
|
||||
|
||||
$query = $this->getAuthorizationQuery($params);
|
||||
return $this->appendQuery($base, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logout url to logout of session token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getBaseLogoutUrl()
|
||||
{
|
||||
return $this->getBaseUrlWithRealm() . '/protocol/openid-connect/logout';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates base url from provider configuration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getBaseUrlWithRealm()
|
||||
{
|
||||
return $this->authServerUrl.'/realms/'.$this->realm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default scopes used by this provider.
|
||||
*
|
||||
* This should not be a complete list of all scopes, but the minimum
|
||||
* required for the provider user interface!
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function getDefaultScopes()
|
||||
{
|
||||
$scopes = [
|
||||
'profile',
|
||||
'email'
|
||||
];
|
||||
if ($this->validateGteVersion('20.0.0')) {
|
||||
$scopes[] = 'openid';
|
||||
}
|
||||
return $scopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the string that should be used to separate scopes when building
|
||||
* the URL for requesting an access token.
|
||||
*
|
||||
* @return string Scope separator, defaults to ','
|
||||
*/
|
||||
protected function getScopeSeparator()
|
||||
{
|
||||
return ' ';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check a provider response for errors.
|
||||
*
|
||||
* @throws IdentityProviderException
|
||||
* @param ResponseInterface $response
|
||||
* @param string $data Parsed response data
|
||||
* @return void
|
||||
*/
|
||||
protected function checkResponse(ResponseInterface $response, $data)
|
||||
{
|
||||
if (!empty($data['error'])) {
|
||||
$error = $data['error'];
|
||||
if (isset($data['error_description'])) {
|
||||
$error.=': '.$data['error_description'];
|
||||
}
|
||||
throw new IdentityProviderException($error, 0, $data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a user object from a successful user details request.
|
||||
*
|
||||
* @param array $response
|
||||
* @param AccessToken $token
|
||||
* @return KeycloakResourceOwner
|
||||
*/
|
||||
protected function createResourceOwner(array $response, AccessToken $token)
|
||||
{
|
||||
return new KeycloakResourceOwner($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests and returns the resource owner of given access token.
|
||||
*
|
||||
* @param AccessToken $token
|
||||
* @return KeycloakResourceOwner
|
||||
* @throws EncryptionConfigurationException
|
||||
*/
|
||||
public function getResourceOwner(AccessToken $token)
|
||||
{
|
||||
$response = $this->fetchResourceOwnerDetails($token);
|
||||
|
||||
// We are always getting an array. We have to check if it is
|
||||
// the array we created
|
||||
if (array_key_exists('jwt', $response)) {
|
||||
$response = $response['jwt'];
|
||||
}
|
||||
|
||||
$response = $this->decryptResponse($response);
|
||||
|
||||
return $this->createResourceOwner($response, $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates expected encryption algorithm of Keycloak instance.
|
||||
*
|
||||
* @param string $encryptionAlgorithm
|
||||
*
|
||||
* @return Keycloak
|
||||
*/
|
||||
public function setEncryptionAlgorithm($encryptionAlgorithm)
|
||||
{
|
||||
$this->encryptionAlgorithm = $encryptionAlgorithm;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates expected encryption key of Keycloak instance.
|
||||
*
|
||||
* @param string $encryptionKey
|
||||
*
|
||||
* @return Keycloak
|
||||
*/
|
||||
public function setEncryptionKey($encryptionKey)
|
||||
{
|
||||
$this->encryptionKey = $encryptionKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates expected encryption key of Keycloak instance to content of given
|
||||
* file path.
|
||||
*
|
||||
* @param string $encryptionKeyPath
|
||||
*
|
||||
* @return Keycloak
|
||||
*/
|
||||
public function setEncryptionKeyPath($encryptionKeyPath)
|
||||
{
|
||||
try {
|
||||
$this->encryptionKey = file_get_contents($encryptionKeyPath);
|
||||
} catch (Exception $e) {
|
||||
// Not sure how to handle this yet.
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the keycloak version.
|
||||
*
|
||||
* @param string $version
|
||||
*
|
||||
* @return Keycloak
|
||||
*/
|
||||
public function setVersion($version)
|
||||
{
|
||||
$this->version = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if provider is configured to use encryption.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function usesEncryption()
|
||||
{
|
||||
return (bool) $this->encryptionAlgorithm && $this->encryptionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the response according to its content-type header.
|
||||
*
|
||||
* @throws UnexpectedValueException
|
||||
* @param ResponseInterface $response
|
||||
* @return array
|
||||
*/
|
||||
protected function parseResponse(ResponseInterface $response)
|
||||
{
|
||||
// We have a problem with keycloak when the userinfo responses
|
||||
// with a jwt token
|
||||
// Because it just return a jwt as string with the header
|
||||
// application/jwt
|
||||
// This can't be parsed to a array
|
||||
// Dont know why this function only allow an array as return value...
|
||||
$content = (string) $response->getBody();
|
||||
$type = $this->getContentType($response);
|
||||
|
||||
if (strpos($type, 'jwt') !== false) {
|
||||
// Here we make the temporary array
|
||||
return ['jwt' => $content];
|
||||
}
|
||||
|
||||
return parent::parseResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if version is greater or equal
|
||||
*
|
||||
* @param string $version
|
||||
* @return bool
|
||||
*/
|
||||
private function validateGteVersion($version)
|
||||
{
|
||||
return (isset($this->version) && version_compare($this->version, $version, '>='));
|
||||
}
|
||||
}
|
65
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/src/Provider/KeycloakResourceOwner.php
vendored
Normal file
65
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/src/Provider/KeycloakResourceOwner.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Stevenmaguire\OAuth2\Client\Provider;
|
||||
|
||||
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
|
||||
|
||||
class KeycloakResourceOwner implements ResourceOwnerInterface
|
||||
{
|
||||
/**
|
||||
* Raw response
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* Creates new resource owner.
|
||||
*
|
||||
* @param array $response
|
||||
*/
|
||||
public function __construct(array $response = array())
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource owner id
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return \array_key_exists('sub', $this->response) ? $this->response['sub'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource owner email
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getEmail()
|
||||
{
|
||||
return \array_key_exists('email', $this->response) ? $this->response['email'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resource owner name
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return \array_key_exists('name', $this->response) ? $this->response['name'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all of the owner details available as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
}
|
306
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/test/src/Provider/KeycloakTest.php
vendored
Normal file
306
data/web/inc/lib/vendor/stevenmaguire/oauth2-keycloak/test/src/Provider/KeycloakTest.php
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
namespace
|
||||
{
|
||||
$mockFileGetContents = null;
|
||||
}
|
||||
|
||||
namespace Stevenmaguire\OAuth2\Client\Provider
|
||||
{
|
||||
function file_get_contents()
|
||||
{
|
||||
global $mockFileGetContents;
|
||||
if (isset($mockFileGetContents) && ! is_null($mockFileGetContents)) {
|
||||
if (is_a($mockFileGetContents, 'Exception')) {
|
||||
throw $mockFileGetContents;
|
||||
}
|
||||
return $mockFileGetContents;
|
||||
} else {
|
||||
return call_user_func_array('\file_get_contents', func_get_args());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Stevenmaguire\OAuth2\Client\Test\Provider
|
||||
{
|
||||
use League\OAuth2\Client\Tool\QueryBuilderTrait;
|
||||
use Mockery as m;
|
||||
|
||||
class KeycloakTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
use QueryBuilderTrait;
|
||||
|
||||
protected $provider;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'authServerUrl' => 'http://mock.url/auth',
|
||||
'realm' => 'mock_realm',
|
||||
'clientId' => 'mock_client_id',
|
||||
'clientSecret' => 'mock_secret',
|
||||
'redirectUri' => 'none',
|
||||
]);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
m::close();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testAuthorizationUrl()
|
||||
{
|
||||
$url = $this->provider->getAuthorizationUrl();
|
||||
$uri = parse_url($url);
|
||||
parse_str($uri['query'], $query);
|
||||
|
||||
$this->assertArrayHasKey('client_id', $query);
|
||||
$this->assertArrayHasKey('redirect_uri', $query);
|
||||
$this->assertArrayHasKey('state', $query);
|
||||
$this->assertArrayHasKey('scope', $query);
|
||||
$this->assertArrayHasKey('response_type', $query);
|
||||
$this->assertArrayHasKey('approval_prompt', $query);
|
||||
$this->assertNotNull($this->provider->getState());
|
||||
}
|
||||
|
||||
public function testEncryptionAlgorithm()
|
||||
{
|
||||
$algorithm = uniqid();
|
||||
$provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'encryptionAlgorithm' => $algorithm,
|
||||
]);
|
||||
|
||||
$this->assertEquals($algorithm, $provider->encryptionAlgorithm);
|
||||
|
||||
$algorithm = uniqid();
|
||||
$provider->setEncryptionAlgorithm($algorithm);
|
||||
|
||||
$this->assertEquals($algorithm, $provider->encryptionAlgorithm);
|
||||
}
|
||||
|
||||
public function testEncryptionKey()
|
||||
{
|
||||
$key = uniqid();
|
||||
$provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'encryptionKey' => $key,
|
||||
]);
|
||||
|
||||
$this->assertEquals($key, $provider->encryptionKey);
|
||||
|
||||
$key = uniqid();
|
||||
$provider->setEncryptionKey($key);
|
||||
|
||||
$this->assertEquals($key, $provider->encryptionKey);
|
||||
}
|
||||
|
||||
public function testEncryptionKeyPath()
|
||||
{
|
||||
global $mockFileGetContents;
|
||||
$path = uniqid();
|
||||
$key = uniqid();
|
||||
$mockFileGetContents = $key;
|
||||
|
||||
$provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'encryptionKeyPath' => $path,
|
||||
]);
|
||||
|
||||
$this->assertEquals($key, $provider->encryptionKey);
|
||||
|
||||
$path = uniqid();
|
||||
$key = uniqid();
|
||||
$mockFileGetContents = $key;
|
||||
|
||||
$provider->setEncryptionKeyPath($path);
|
||||
|
||||
$this->assertEquals($key, $provider->encryptionKey);
|
||||
}
|
||||
|
||||
public function testEncryptionKeyPathFails()
|
||||
{
|
||||
global $mockFileGetContents;
|
||||
$path = uniqid();
|
||||
$key = uniqid();
|
||||
$mockFileGetContents = new \Exception();
|
||||
|
||||
$provider = new \Stevenmaguire\OAuth2\Client\Provider\Keycloak([
|
||||
'encryptionKeyPath' => $path,
|
||||
]);
|
||||
|
||||
$provider->setEncryptionKeyPath($path);
|
||||
}
|
||||
|
||||
public function testScopes()
|
||||
{
|
||||
$scopeSeparator = ' ';
|
||||
$options = ['scope' => [uniqid(), uniqid()]];
|
||||
$query = ['scope' => implode($scopeSeparator, $options['scope'])];
|
||||
$url = $this->provider->getAuthorizationUrl($options);
|
||||
$encodedScope = $this->buildQueryString($query);
|
||||
$this->assertContains($encodedScope, $url);
|
||||
}
|
||||
|
||||
public function testGetAuthorizationUrl()
|
||||
{
|
||||
$url = $this->provider->getAuthorizationUrl();
|
||||
$uri = parse_url($url);
|
||||
|
||||
$this->assertEquals('/auth/realms/mock_realm/protocol/openid-connect/auth', $uri['path']);
|
||||
}
|
||||
|
||||
public function testGetLogoutUrl()
|
||||
{
|
||||
$url = $this->provider->getLogoutUrl();
|
||||
$uri = parse_url($url);
|
||||
|
||||
$this->assertEquals('/auth/realms/mock_realm/protocol/openid-connect/logout', $uri['path']);
|
||||
}
|
||||
|
||||
public function testGetBaseAccessTokenUrl()
|
||||
{
|
||||
$params = [];
|
||||
|
||||
$url = $this->provider->getBaseAccessTokenUrl($params);
|
||||
$uri = parse_url($url);
|
||||
|
||||
$this->assertEquals('/auth/realms/mock_realm/protocol/openid-connect/token', $uri['path']);
|
||||
}
|
||||
|
||||
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']);
|
||||
|
||||
$client = m::mock('GuzzleHttp\ClientInterface');
|
||||
$client->shouldReceive('send')->times(1)->andReturn($response);
|
||||
$this->provider->setHttpClient($client);
|
||||
|
||||
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
|
||||
|
||||
$this->assertEquals('mock_access_token', $token->getToken());
|
||||
$this->assertNull($token->getExpires());
|
||||
$this->assertNull($token->getRefreshToken());
|
||||
$this->assertNull($token->getResourceOwnerId());
|
||||
}
|
||||
|
||||
public function testUserData()
|
||||
{
|
||||
$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']);
|
||||
|
||||
$userResponse = m::mock('Psr\Http\Message\ResponseInterface');
|
||||
$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')
|
||||
->times(2)
|
||||
->andReturn($postResponse, $userResponse);
|
||||
$this->provider->setHttpClient($client);
|
||||
|
||||
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
|
||||
$user = $this->provider->getResourceOwner($token);
|
||||
|
||||
$this->assertEquals($userId, $user->getId());
|
||||
$this->assertEquals($userId, $user->toArray()['sub']);
|
||||
$this->assertEquals($name, $user->getName());
|
||||
$this->assertEquals($name, $user->toArray()['name']);
|
||||
$this->assertEquals($email, $user->getEmail());
|
||||
$this->assertEquals($email, $user->toArray()['email']);
|
||||
}
|
||||
|
||||
public function testUserDataWithEncryption()
|
||||
{
|
||||
$userId = rand(1000,9999);
|
||||
$name = uniqid();
|
||||
$nickname = uniqid();
|
||||
$email = uniqid();
|
||||
$jwt = uniqid();
|
||||
$algorithm = uniqid();
|
||||
$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);
|
||||
|
||||
$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);
|
||||
|
||||
$decoder = \Mockery::mock('overload:Firebase\JWT\JWT');
|
||||
$decoder->shouldReceive('decode')->with($jwt, $key, [$algorithm])->andReturn([
|
||||
'sub' => $userId,
|
||||
'email' => $email,
|
||||
'name' => $name,
|
||||
]);
|
||||
|
||||
$client = m::mock('GuzzleHttp\ClientInterface');
|
||||
$client->shouldReceive('send')
|
||||
->times(2)
|
||||
->andReturn($postResponse, $userResponse);
|
||||
$this->provider->setHttpClient($client);
|
||||
|
||||
$token = $this->provider->setEncryptionAlgorithm($algorithm)
|
||||
->setEncryptionKey($key)
|
||||
->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
|
||||
$user = $this->provider->getResourceOwner($token);
|
||||
|
||||
$this->assertEquals($userId, $user->getId());
|
||||
$this->assertEquals($userId, $user->toArray()['sub']);
|
||||
$this->assertEquals($name, $user->getName());
|
||||
$this->assertEquals($name, $user->toArray()['name']);
|
||||
$this->assertEquals($email, $user->getEmail());
|
||||
$this->assertEquals($email, $user->toArray()['email']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Stevenmaguire\OAuth2\Client\Provider\Exception\EncryptionConfigurationException
|
||||
*/
|
||||
public function testUserDataFailsWhenEncryptionEncounteredAndNotConfigured()
|
||||
{
|
||||
$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);
|
||||
|
||||
$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);
|
||||
|
||||
$client = m::mock('GuzzleHttp\ClientInterface');
|
||||
$client->shouldReceive('send')
|
||||
->times(2)
|
||||
->andReturn($postResponse, $userResponse);
|
||||
$this->provider->setHttpClient($client);
|
||||
|
||||
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
|
||||
$user = $this->provider->getResourceOwner($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException League\OAuth2\Client\Provider\Exception\IdentityProviderException
|
||||
*/
|
||||
public function testErrorResponse()
|
||||
{
|
||||
$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']);
|
||||
|
||||
$client = m::mock('GuzzleHttp\ClientInterface');
|
||||
$client->shouldReceive('send')->times(1)->andReturn($response);
|
||||
$this->provider->setHttpClient($client);
|
||||
|
||||
$token = $this->provider->getAccessToken('authorization_code', ['code' => 'mock_authorization_code']);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user