From d6ed1633a62343573bc05139b33cdf93f7d2107f Mon Sep 17 00:00:00 2001 From: Kevin <34477826+kkevindev@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:47:11 +0200 Subject: [PATCH 1/3] Added support for optional audience and organization options. --- .../ResourceOwner/Auth0ResourceOwner.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/OAuth/ResourceOwner/Auth0ResourceOwner.php b/src/OAuth/ResourceOwner/Auth0ResourceOwner.php index 233cd6823..e8a381bbd 100644 --- a/src/OAuth/ResourceOwner/Auth0ResourceOwner.php +++ b/src/OAuth/ResourceOwner/Auth0ResourceOwner.php @@ -55,6 +55,11 @@ protected function configureOptions(OptionsResolver $resolver) 'auth0_client' => $auth0Client, ]); + $resolver->setDefined([ + 'organization', + 'audience', + ]); + $resolver->setRequired([ 'base_url', ]); @@ -79,4 +84,20 @@ protected function httpRequest($url, $content = null, array $headers = [], $meth return parent::httpRequest($url, $content, $headers, $method); } + + /** + * {@inheritDoc} + */ + public function getAuthorizationUrl($redirectUri, array $extraParameters = []): string + { + if (!empty($this->options['organization'])) { + $extraParameters['organization'] = $this->options['organization']; + } + + if (!empty($this->options['audience'])) { + $extraParameters['audience'] = $this->options['audience']; + } + + return parent::getAuthorizationUrl($redirectUri, $extraParameters); + } } From c7d9c7847f9f5376c1a4cfe0d8ceedc1c6cf6a6e Mon Sep 17 00:00:00 2001 From: Kevin <34477826+kkevindev@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:01:30 +0200 Subject: [PATCH 2/3] Updated documentation for configuring the Auth0 ResourceOwner. --- docs/resource_owners/auth0.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/resource_owners/auth0.md b/docs/resource_owners/auth0.md index 3c3f5f940..7e746131a 100644 --- a/docs/resource_owners/auth0.md +++ b/docs/resource_owners/auth0.md @@ -11,11 +11,28 @@ Next configure a resource owner of type `auth0` with appropriate `client_id`, hwi_oauth: resource_owners: any_name: - type: auth0 - client_id: - client_secret: - base_url: https:// - scope: + type: auth0 + client_id: + client_secret: + base_url: https:// + scope: +``` + +Optionally, you can configure the `organization` and `audience` options when the login flow for the application requires this: +```yaml +# config/packages/hwi_oauth.yaml + +hwi_oauth: + resource_owners: + any_name: + type: auth0 + client_id: + client_secret: + base_url: https:// + scope: + options: + organization: + audience: ``` When you're done. Continue by configuring the security layer or go back to From 0b81302bf703b326590b625cb5a4d5d810a96c7d Mon Sep 17 00:00:00 2001 From: Kevin <34477826+kkevindev@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:34:04 +0200 Subject: [PATCH 3/3] Fixed php-cs-fixer issues. --- .../ResourceOwner/Auth0ResourceOwner.php | 32 +++++++++---------- .../ResourceOwner/KeycloakResourceOwner.php | 24 +++++++------- tests/App/Form/RegistrationFormType.php | 4 +-- .../App/ResourceOwner/CustomResourceOwner.php | 8 ++--- .../KeycloakResourceOwnerTest.php | 16 +++++----- tests/Security/Http/RefreshOnExpireTest.php | 6 ++-- 6 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/OAuth/ResourceOwner/Auth0ResourceOwner.php b/src/OAuth/ResourceOwner/Auth0ResourceOwner.php index e8a381bbd..4d089151c 100644 --- a/src/OAuth/ResourceOwner/Auth0ResourceOwner.php +++ b/src/OAuth/ResourceOwner/Auth0ResourceOwner.php @@ -32,6 +32,22 @@ final class Auth0ResourceOwner extends GenericOAuth2ResourceOwner 'profilepicture' => 'picture', ]; + /** + * {@inheritDoc} + */ + public function getAuthorizationUrl($redirectUri, array $extraParameters = []): string + { + if (!empty($this->options['organization'])) { + $extraParameters['organization'] = $this->options['organization']; + } + + if (!empty($this->options['audience'])) { + $extraParameters['audience'] = $this->options['audience']; + } + + return parent::getAuthorizationUrl($redirectUri, $extraParameters); + } + /** * {@inheritdoc} */ @@ -84,20 +100,4 @@ protected function httpRequest($url, $content = null, array $headers = [], $meth return parent::httpRequest($url, $content, $headers, $method); } - - /** - * {@inheritDoc} - */ - public function getAuthorizationUrl($redirectUri, array $extraParameters = []): string - { - if (!empty($this->options['organization'])) { - $extraParameters['organization'] = $this->options['organization']; - } - - if (!empty($this->options['audience'])) { - $extraParameters['audience'] = $this->options['audience']; - } - - return parent::getAuthorizationUrl($redirectUri, $extraParameters); - } } diff --git a/src/OAuth/ResourceOwner/KeycloakResourceOwner.php b/src/OAuth/ResourceOwner/KeycloakResourceOwner.php index 148dbb58f..8e19225f6 100644 --- a/src/OAuth/ResourceOwner/KeycloakResourceOwner.php +++ b/src/OAuth/ResourceOwner/KeycloakResourceOwner.php @@ -34,8 +34,8 @@ final class KeycloakResourceOwner extends GenericOAuth2ResourceOwner public function getAuthorizationUrl($redirectUri, array $extraParameters = []) { return parent::getAuthorizationUrl($redirectUri, array_merge([ - 'approval_prompt' => $this->getOption('approval_prompt'), - 'kc_idp_hint' => $this->getOption('idp_hint'), + 'approval_prompt' => $this->getOption('approval_prompt'), + 'kc_idp_hint' => $this->getOption('idp_hint'), ], $extraParameters)); } @@ -44,19 +44,19 @@ protected function configureOptions(OptionsResolver $resolver) parent::configureOptions($resolver); $resolver->setDefaults([ - 'protocol' => 'openid-connect', - 'scope' => 'openid email', - 'response_type' => 'code', - 'approval_prompt' => 'auto', - 'authorization_url' => '{keycloak_url}/auth', - 'access_token_url' => '{keycloak_url}/token', - 'infos_url' => '{keycloak_url}/userinfo', - 'idp_hint' => null, + 'protocol' => 'openid-connect', + 'scope' => 'openid email', + 'response_type' => 'code', + 'approval_prompt' => 'auto', + 'authorization_url' => '{keycloak_url}/auth', + 'access_token_url' => '{keycloak_url}/token', + 'infos_url' => '{keycloak_url}/userinfo', + 'idp_hint' => null, ]); $resolver->setRequired([ - 'realm', - 'base_url', + 'realm', + 'base_url', ]); $normalizer = function (Options $options, $value) { diff --git a/tests/App/Form/RegistrationFormType.php b/tests/App/Form/RegistrationFormType.php index ffe9df1dd..51ace4ac7 100644 --- a/tests/App/Form/RegistrationFormType.php +++ b/tests/App/Form/RegistrationFormType.php @@ -53,8 +53,8 @@ public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults( [ - 'data_class' => User::class, - 'csrf_token_id' => 'registration', + 'data_class' => User::class, + 'csrf_token_id' => 'registration', ] ); } diff --git a/tests/App/ResourceOwner/CustomResourceOwner.php b/tests/App/ResourceOwner/CustomResourceOwner.php index b7346d1e8..a41e06e76 100644 --- a/tests/App/ResourceOwner/CustomResourceOwner.php +++ b/tests/App/ResourceOwner/CustomResourceOwner.php @@ -36,10 +36,10 @@ protected function configureOptions(OptionsResolver $resolver): void $resolver->setDefaults( [ - 'authorization_url' => '{base_url}/authorize', - 'access_token_url' => '{base_url}/oauth/token', - 'infos_url' => '{base_url}/userinfo', - ] + 'authorization_url' => '{base_url}/authorize', + 'access_token_url' => '{base_url}/oauth/token', + 'infos_url' => '{base_url}/userinfo', + ] ); $resolver->setRequired(['base_url']); diff --git a/tests/OAuth/ResourceOwner/KeycloakResourceOwnerTest.php b/tests/OAuth/ResourceOwner/KeycloakResourceOwnerTest.php index 80e25d872..6b974d143 100644 --- a/tests/OAuth/ResourceOwner/KeycloakResourceOwnerTest.php +++ b/tests/OAuth/ResourceOwner/KeycloakResourceOwnerTest.php @@ -17,16 +17,16 @@ final class KeycloakResourceOwnerTest extends GenericOAuth2ResourceOwnerTestCase { protected array $options = [ - 'base_url' => 'http://keycloak.example.com/auth', - 'realm' => 'example', - 'client_id' => 'clientid', - 'client_secret' => 'clientsecret', + 'base_url' => 'http://keycloak.example.com/auth', + 'realm' => 'example', + 'client_id' => 'clientid', + 'client_secret' => 'clientsecret', - 'authorization_url' => 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/auth', - 'access_token_url' => 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/token', - 'infos_url' => 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/userinfo', + 'authorization_url' => 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/auth', + 'access_token_url' => 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/token', + 'infos_url' => 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/userinfo', - 'attr_name' => 'access_token', + 'attr_name' => 'access_token', ]; protected string $authorizationUrlBasePart = 'http://keycloak.example.com/auth/realms/example/protocol/openid-connect/auth?response_type=code&client_id=clientid&scope=openid+email'; diff --git a/tests/Security/Http/RefreshOnExpireTest.php b/tests/Security/Http/RefreshOnExpireTest.php index c54c3099f..6f6be7b94 100644 --- a/tests/Security/Http/RefreshOnExpireTest.php +++ b/tests/Security/Http/RefreshOnExpireTest.php @@ -76,9 +76,9 @@ public function testTokenIsExpiredSuccessfulRefresh() $this->resourceOwnerMock->expects($this->once()) ->method('refreshAccessToken') ->willReturn([ - 'expires' => 666, // expired - 'refresh_token' => 'refresh_token', - ]); + 'expires' => 666, // expired + 'refresh_token' => 'refresh_token', + ]); $this->resourceOwnerMock->expects($this->once()) ->method('getUserInformation')