Skip to content
Merged

OAuth2 #5753

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Vendor: SSO: Add stevenmaguire/oauth2-keycloak + implement keycloak l…
…ogin/registration - refs BT#21881
  • Loading branch information
AngelFQC committed Aug 27, 2024
commit 227076163d63cc37f08494cb4266ee4b6c79d2cb
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 12 additions & 0 deletions config/authentication.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: { }
9 changes: 9 additions & 0 deletions config/packages/knpu_oauth2_client.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
26 changes: 26 additions & 0 deletions src/CoreBundle/Controller/OAuth2/KeycloakProviderController.php
Original file line number Diff line number Diff line change
@@ -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 {}
}
2 changes: 2 additions & 0 deletions src/CoreBundle/Decorator/OAuth2ProviderFactoryDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
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;

Expand All @@ -35,6 +36,7 @@ public function createProvider(
$options = match ($class) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space before opening parenthesis of function call prohibited

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Space before opening parenthesis of function call prohibited

GenericProvider::class => $this->getProviderOptions('generic'),
Facebook::class => $this->getProviderOptions('facebook'),
Keycloak::class => $this->getProviderOptions('keycloak'),
};

return $this->inner->createProvider($class, $options, $redirectUri, $redirectParams, $collaborators);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}