Vendor: SSO: Add stevenmaguire/oauth2-keycloak + implement keycloak login/registration - refs BT#21881

pull/5753/head
Angel Fernando Quiroz Campos 1 year ago
parent 007d59dc65
commit 227076163d
No known key found for this signature in database
GPG Key ID: B284841AE3E562CD
  1. 1
      composer.json
  2. 12
      config/authentication.yaml
  3. 9
      config/packages/knpu_oauth2_client.yaml
  4. 1
      config/packages/security.yaml
  5. 26
      src/CoreBundle/Controller/OAuth2/KeycloakProviderController.php
  6. 2
      src/CoreBundle/Decorator/OAuth2ProviderFactoryDecorator.php
  7. 57
      src/CoreBundle/Security/Authenticator/OAuth2/KeycloakAuthenticator.php

@ -117,6 +117,7 @@
"sensio/framework-extra-bundle": "~6.1",
"simpod/doctrine-utcdatetime": "^0.1.2",
"sonata-project/exporter": "^2.2",
"stevenmaguire/oauth2-keycloak": "^5.1",
"stof/doctrine-extensions-bundle": "^1.10",
"sunra/php-simple-html-dom-parser": "~1.5",
"symfony/apache-pack": "^1.0",

@ -34,3 +34,15 @@ parameters:
client_secret: ''
graph_api_version: 'v20.0'
redirect_params: { }
keycloak:
enabled: false
client_id: ''
client_secret: ''
auth_server_url: ''
realm: ''
version: ''
encryption_algorithm: null
encryption_key_path: null
encryption_key: null
redirect_params: { }

@ -15,4 +15,13 @@ knpu_oauth2_client:
graph_api_version: ''
redirect_params: { }
keycloak:
type: keycloak
client_id: ''
client_secret: ''
redirect_route: chamilo.oauth2_keycloak_check
redirect_params: { }
auth_server_url: null
realm: null
# configure your clients as described here: https://github.com/knpuniversity/oauth2-client-bundle#configuration

@ -117,6 +117,7 @@ security:
custom_authenticators:
- Chamilo\CoreBundle\Security\Authenticator\OAuth2\GenericAuthenticator
- Chamilo\CoreBundle\Security\Authenticator\OAuth2\FacebookAuthenticator
- Chamilo\CoreBundle\Security\Authenticator\OAuth2\KeycloakAuthenticator
access_control:
- {path: ^/login, roles: PUBLIC_ACCESS}

@ -0,0 +1,26 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Controller\OAuth2;
use Chamilo\CoreBundle\ServiceHelper\AuthenticationConfigHelper;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class KeycloakProviderController extends AbstractProviderController
{
#[Route('/connect/keycloak', name: 'chamilo.oauth2_keycloak_start')]
public function connect(
ClientRegistry $clientRegistry,
AuthenticationConfigHelper $authenticationConfigHelper,
): Response {
return $this->getStartResponse('keycloak', $clientRegistry, $authenticationConfigHelper);
}
#[Route('/connect/keycloak/check', name: 'chamilo.oauth2_keycloak_check')]
public function connectCheck(): void {}
}

@ -13,6 +13,7 @@ use KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Facebook;
use League\OAuth2\Client\Provider\GenericProvider;
use Stevenmaguire\OAuth2\Client\Provider\Keycloak;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
@ -35,6 +36,7 @@ readonly class OAuth2ProviderFactoryDecorator
$options = match ($class) {
GenericProvider::class => $this->getProviderOptions('generic'),
Facebook::class => $this->getProviderOptions('facebook'),
Keycloak::class => $this->getProviderOptions('keycloak'),
};
return $this->inner->createProvider($class, $options, $redirectUri, $redirectParams, $collaborators);

@ -0,0 +1,57 @@
<?php
/* For licensing terms, see /license.txt */
declare(strict_types=1);
namespace Chamilo\CoreBundle\Security\Authenticator\OAuth2;
use Chamilo\CoreBundle\Entity\User;
use KnpU\OAuth2ClientBundle\Client\OAuth2ClientInterface;
use League\OAuth2\Client\Token\AccessToken;
use Stevenmaguire\OAuth2\Client\Provider\KeycloakResourceOwner;
use Symfony\Component\HttpFoundation\Request;
class KeycloakAuthenticator extends AbstractAuthenticator
{
protected string $providerName = 'keycloak';
public function supports(Request $request): ?bool
{
return 'chamilo.oauth2_keycloak_check' === $request->attributes->get('_route');
}
protected function userLoader(AccessToken $accessToken): User
{
/** @var KeycloakResourceOwner $resourceOwner */
$resourceOwner = $this->client->fetchUserFromToken($accessToken);
$user = $this->userRepository->findOneBy(['username' => $resourceOwner->getUsername()])
?:
$this->userRepository->findOneBy(['username' => $resourceOwner->getId()]);
if (!$user) {
$user = (new User())
->setCreatorId($this->userRepository->getRootUser()->getId())
;
}
$username = $resourceOwner->getUsername() ?: $resourceOwner->getId();
$user
->setFirstname($resourceOwner->getFirstName())
->setLastname($resourceOwner->getLastName())
->setEmail($resourceOwner->getEmail())
->setUsername($username)
->setPlainPassword('keycloak')
->setStatus(STUDENT)
->setAuthSource('keycloak')
->setRoleFromStatus(STUDENT)
;
$this->userRepository->updateUser($user);
// updateAccessUrls ?
return $user;
}
}
Loading…
Cancel
Save