-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update v2.x-automation-test for micro/plugin-oauth2-client-keycloak
- Loading branch information
1 parent
a794ebb
commit 18cad42
Showing
8 changed files
with
488 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* This file is part of the Micro framework package. | ||
* | ||
* (c) Stanislau Komar <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Micro\Plugin\OAuth2\Keycloak\Client\Configuration\Provider; | ||
|
||
use Micro\Plugin\OAuth2\Client\Configuration\Provider\OAuth2ClientProviderConfiguration; | ||
use Micro\Plugin\OAuth2\Keycloak\Client\Provider\KeycloakProviderConfigurationInterface; | ||
|
||
/** | ||
* @author Stanislau Komar <[email protected]> | ||
*/ | ||
class ProviderConfiguration extends OAuth2ClientProviderConfiguration implements KeycloakProviderConfigurationInterface | ||
{ | ||
const CFG_REALM = 'MICRO_OAUTH2_%s_REALM'; | ||
const CFG_SCOPES = 'MICRO_OAUTH2_%s_SCOPES'; | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getRealm(): string | ||
{ | ||
return $this->get(self::CFG_REALM, 'micro'); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getScopesDefault(): array | ||
{ | ||
return $this->explodeStringToArray($this->get(self::CFG_SCOPES, 'email,profile')); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getScopesSeparator(): string | ||
{ | ||
return ' '; | ||
} | ||
|
||
public function getSecurityProvider(): string|null | ||
{ | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 Komar Stanislau | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* This file is part of the Micro framework package. | ||
* | ||
* (c) Stanislau Komar <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Micro\Plugin\OAuth2\Keycloak\Client; | ||
|
||
use League\OAuth2\Client\Provider\AbstractProvider; | ||
use Micro\Framework\DependencyInjection\Container; | ||
use Micro\Framework\BootConfiguration\Plugin\ConfigurableInterface; | ||
use Micro\Framework\BootDependency\Plugin\DependencyProviderInterface; | ||
use Micro\Framework\BootConfiguration\Plugin\PluginConfigurationTrait; | ||
use Micro\Plugin\OAuth2\Client\Configuration\OAuth2ClientPluginConfigurationInterface; | ||
use Micro\Plugin\OAuth2\Keycloak\Client\Provider\OAuth2Provider; | ||
use Micro\Plugin\OAuth2\Client\Provider\OAuth2ClientProviderPluginInterface; | ||
use Micro\Plugin\Security\Facade\SecurityFacadeInterface; | ||
|
||
/** | ||
* @author Stanislau Komar <[email protected]> | ||
* | ||
* @method OAuth2ClientPluginConfigurationInterface configuration() | ||
*/ | ||
class OAuth2KeycloakProviderPlugin implements OAuth2ClientProviderPluginInterface, DependencyProviderInterface, ConfigurableInterface | ||
{ | ||
|
||
use PluginConfigurationTrait; | ||
|
||
const PROVIDER_TYPE = 'keycloak'; | ||
|
||
/** | ||
* @var Container | ||
*/ | ||
private readonly Container $container; | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function createProvider(string $providerName): AbstractProvider | ||
{ | ||
return new OAuth2Provider( | ||
$this->configuration()->getProviderConfiguration($providerName), | ||
$this->container->get(SecurityFacadeInterface::class), | ||
); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getType(): string | ||
{ | ||
return self::PROVIDER_TYPE; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function provideDependencies(Container $container): void | ||
{ | ||
$this->container = $container; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* This file is part of the Micro framework package. | ||
* | ||
* (c) Stanislau Komar <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Micro\Plugin\OAuth2\Keycloak\Client; | ||
|
||
use Micro\Plugin\OAuth2\Client\Configuration\Provider\OAuth2ClientProviderConfigurationInterface; | ||
use Micro\Plugin\OAuth2\Client\OAuth2ClientPluginConfiguration; | ||
use Micro\Plugin\OAuth2\Keycloak\Client\Configuration\Provider\ProviderConfiguration; | ||
|
||
/** | ||
* @author Stanislau Komar <[email protected]> | ||
*/ | ||
class OAuth2KeycloakProviderPluginConfiguration extends OAuth2ClientPluginConfiguration | ||
{ | ||
/** | ||
* @param string $providerName | ||
* | ||
* @return OAuth2ClientProviderConfigurationInterface | ||
*/ | ||
public function getProviderConfiguration(string $providerName): OAuth2ClientProviderConfigurationInterface | ||
{ | ||
return new ProviderConfiguration($this->configuration, $providerName); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
Client/Provider/KeycloakProviderConfigurationInterface.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* This file is part of the Micro framework package. | ||
* | ||
* (c) Stanislau Komar <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Micro\Plugin\OAuth2\Keycloak\Client\Provider; | ||
|
||
use Micro\Plugin\OAuth2\Client\Configuration\Provider\OAuth2ClientProviderConfigurationInterface; | ||
|
||
/** | ||
* @author Stanislau Komar <[email protected]> | ||
*/ | ||
interface KeycloakProviderConfigurationInterface extends OAuth2ClientProviderConfigurationInterface | ||
{ | ||
/** | ||
* @return string | ||
*/ | ||
public function getRealm(): string; | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function getScopesDefault(): array; | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function getScopesSeparator(): string; | ||
|
||
/** | ||
* @return string|null | ||
*/ | ||
public function getSecurityProvider(): string|null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/** | ||
* This file is part of the Micro framework package. | ||
* | ||
* (c) Stanislau Komar <[email protected]> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Micro\Plugin\OAuth2\Keycloak\Client\Provider; | ||
|
||
use League\OAuth2\Client\Provider\AbstractProvider; | ||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException; | ||
use League\OAuth2\Client\Provider\ResourceOwnerInterface; | ||
use League\OAuth2\Client\Token\AccessToken; | ||
use League\OAuth2\Client\Tool\BearerAuthorizationTrait; | ||
use Micro\Plugin\OAuth2\Client\Configuration\Provider\OAuth2ClientProviderConfigurationInterface; | ||
use Micro\Plugin\Security\Facade\SecurityFacadeInterface; | ||
use Psr\Http\Message\ResponseInterface; | ||
|
||
/** | ||
* @author Stanislau Komar <[email protected]> | ||
*/ | ||
class OAuth2Provider extends AbstractProvider | ||
{ | ||
use BearerAuthorizationTrait; | ||
|
||
/** | ||
* @param OAuth2ClientProviderConfigurationInterface $providerConfiguration | ||
* @param SecurityFacadeInterface $securityFacade | ||
*/ | ||
public function __construct( | ||
private readonly OAuth2ClientProviderConfigurationInterface $providerConfiguration, | ||
private readonly SecurityFacadeInterface $securityFacade | ||
) { | ||
parent::__construct([ | ||
'authServerUrl' => $this->providerConfiguration->getUrlAuthorization(), | ||
'clientId' => $providerConfiguration->getClientId(), | ||
'clientSecret' => $this->providerConfiguration->getClientSecret(), | ||
'redirectUri' => $this->providerConfiguration->getUrlRedirect(), | ||
],[]); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getBaseAuthorizationUrl(): string | ||
{ | ||
return $this->getBaseUrlWithRealm() . '/protocol/openid-connect/auth'; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getBaseAccessTokenUrl(array $params): string | ||
{ | ||
return $this->getBaseUrlWithRealm() . '/protocol/openid-connect/token'; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getResourceOwnerDetailsUrl(AccessToken $token): string | ||
{ | ||
return $this->getBaseUrlWithRealm() . '/protocol/openid-connect/userinfo'; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
protected function getBaseUrlWithRealm(): string | ||
{ | ||
return | ||
$this->providerConfiguration->getUrlAuthorization() . | ||
'/realms/' . | ||
$this->providerConfiguration->getRealm(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function getDefaultScopes(): array | ||
{ | ||
return $this->providerConfiguration->getScopesDefault(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function checkResponse(ResponseInterface $response, $data): void | ||
{ | ||
if(is_string($data)) { | ||
throw new IdentityProviderException('Invalid response data', 0, $data); | ||
} | ||
|
||
if (empty($data['error'])) { | ||
return; | ||
} | ||
|
||
$error = $data['error']; | ||
|
||
if(isset($data['error_description'])){ | ||
$error .= ': ' . $data['error_description']; | ||
} | ||
|
||
throw new IdentityProviderException($error, 0, $data); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function getResourceOwner(AccessToken $token): ResourceOwnerInterface | ||
{ | ||
$response = $this->fetchResourceOwnerDetails($token); | ||
if (array_key_exists('jwt', $response)) { | ||
$response = $response['jwt']; | ||
} | ||
|
||
$response = $this->decryptResponse($response); | ||
|
||
return $this->createResourceOwner($response, $token); | ||
} | ||
|
||
/** | ||
* Attempts to decrypt the given response. | ||
* | ||
* @param string|array $response | ||
* | ||
* @return array|null | ||
*/ | ||
public function decryptResponse(string|array $response): array|null | ||
{ | ||
if (!is_string($response)) { | ||
return $response; | ||
} | ||
|
||
return $this->securityFacade | ||
->decodeToken($response) | ||
->getParameters(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function getScopeSeparator(): string | ||
{ | ||
return $this->providerConfiguration->getScopesSeparator(); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface | ||
{ | ||
return new ResourceOwner($response); | ||
} | ||
} |
Oops, something went wrong.