Skip to content

Commit

Permalink
[TASK] Symfony 6 Upgrade (#13)
Browse files Browse the repository at this point in the history
* [TASK] Symfony 6 Upgrade

* Move to KNPU bundle

* Update README.md

* Update composer dependencies

* Fix group evaluation

* Drop Symfony 4 & 5 and PHP 7.4 support, fix cgl

* Add Symfony 5 again, update CI

* Add dependency

* Provide configuration options for routes

* Provide default login/logout actions and move logic into a service class

* Update dependencies and fix CGL

* Fix DI in Symfony 5

* Fix Symfony 5 issues

* Fix CGL

* Code cleanup and comparison fix
  • Loading branch information
buchmarv authored Sep 9, 2024
1 parent 5223e56 commit e326265
Show file tree
Hide file tree
Showing 17 changed files with 415 additions and 300 deletions.
8 changes: 4 additions & 4 deletions .ddev/config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: symfony-keycloak-bundle
type: php
docroot: ""
php_version: "7.4"
php_version: "8.1"
webserver_type: nginx-fpm
router_http_port: "80"
router_https_port: "443"
Expand All @@ -12,7 +12,7 @@ database:
type: mariadb
version: "10.3"
omit_containers: [db]
webimage_extra_packages: [php7.4-gmp, ssh]
webimage_extra_packages: [php8.1-gmp, ssh]
use_dns_when_possible: true
composer_version: "2"
web_environment: []
Expand Down Expand Up @@ -54,7 +54,7 @@ nodejs_version: "18"
# "ddev xhprof" to enable xhprof and "ddev xhprof off" to disable it work better,
# as leaving xhprof enabled all the time is a big performance hit.

# webserver_type: nginx-fpm, apache-fpm, or nginx-gunicorn
# webserver_type: nginx-fpm, apache-fpm, or nginx-gunicorn

# timezone: Europe/Berlin
# This is the timezone used in the containers and by PHP;
Expand Down Expand Up @@ -96,7 +96,7 @@ nodejs_version: "18"
# Please take care with this because it can cause great confusion.

# upload_dirs: "custom/upload/dir"
#
#
# upload_dirs:
# - custom/upload/dir
# - ../private
Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,12 @@ jobs:
strategy:
fail-fast: false
matrix:
symfony: ['^4.4', '^5.4']
php: ['7.4', '8.0', '8.1']
symfony: ['^5.4', '^6.4']
php: ['8.1', '8.2', '8.3']
experimental: [false]
include:
- symfony: '^6.0'
php: '8.0'
experimental: true
- symfony: '^6.0'
php: '8.1'
- symfony: '^7.0'
php: '8.2'
experimental: true

steps:
Expand Down
4 changes: 2 additions & 2 deletions .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
],
'declare_strict_types' => true,
'no_leading_import_slash' => true,
'no_trailing_comma_in_singleline_array' => true,
'no_trailing_comma_in_singleline' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_unused_imports' => true,
'concat_space' => ['spacing' => 'one'],
Expand All @@ -55,7 +55,7 @@
'no_blank_lines_after_phpdoc' => true,
'array_syntax' => ['syntax' => 'short'],
'whitespace_after_comma_in_array' => true,
'function_typehint_space' => true,
'type_declaration_spaces' => true,
'single_line_comment_style' => true,
'no_alias_functions' => true,
'lowercase_cast' => true,
Expand Down
59 changes: 19 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,27 @@ Update your security.yaml like this
```yaml
# config/packages/security.yaml
security:
enable_authenticator_manager: true
providers:
keycloak:
id: keycloak.typo3.com.user.provider
firewalls:
main:
anonymous: true
provider: keycloak
logout:
path: /logout
target: home
guard:
authenticators:
- T3G\Bundle\Keycloak\Security\KeyCloakAuthenticator
custom_authenticators:
- T3G\Bundle\Keycloak\Security\KeyCloakAuthenticator
```
```yaml
# config/routes.yaml
logout:
path: /logout

login:
alias: t3g_keycloak_login
```
## Step 3: Enable the Bundle
Expand All @@ -48,47 +51,13 @@ in the `config/bundles.php` file of your project:
return [
// ...
Jose\Bundle\JoseFramework\JoseFrameworkBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
KnpU\OAuth2ClientBundle\KnpUOAuth2ClientBundle::class => ['all' => true],
Http\HttplugBundle\HttplugBundle::class => ['all' => true],
T3G\Bundle\Keycloak\T3GKeycloakBundle::class => ['all' => true],
];
```

## Step 5: Create a login controller

In order to log in, a simple login controller will suffice:

```php
<?php
namespace App\Controller;
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Annotation\Route;
class HomeController extends AbstractController
{
/**
* Link to this controller to start the "connect" process.
*
* @Route("/login", name="login")
* @param ClientRegistry $clientRegistry
* @return RedirectResponse
*/
public function login(ClientRegistry $clientRegistry): RedirectResponse
{
return $clientRegistry
->getClient('keycloak')
->redirect([
'profile roles email', // the scopes you want to access
], []);
}
}
```

# Configuration

```bash
Expand All @@ -105,12 +74,12 @@ php bin/console debug:config t3g_keycloak
# Default configuration for extension with alias: "t3g_keycloak"
t3g_keycloak:
keycloak:
jku_url: 'https://login.typo3.com/realms/TYPO3/protocol/openid-connect/certs'
user_provider_class: T3G\Bundle\Keycloak\Security\KeyCloakUserProvider
default_roles:
# Defaults:
- ROLE_USER
- ROLE_OAUTH_USER
clientId: '%env(KEYCLOAK_CLIENT_ID)%'
```

### Role Mapping
Expand All @@ -121,3 +90,13 @@ t3g_keycloak:
role_mapping:
my-role: ROLE_ADMIN
```

### Routes
```yaml
t3g_keycloak:
routes:
# route to redirect to after successful authentication
success: home
# redirect_route passed to keycloak
authentication: t3g_keycloak_oauthCallback
```
22 changes: 8 additions & 14 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,20 @@
],
"minimum-stability": "stable",
"require": {
"php": "^7.4 || ^8.0",
"php": "^8.1",
"ext-json": "*",
"ext-gmp": "*",
"knpuniversity/oauth2-client-bundle": "^2.18",
"nyholm/psr7": "^1.2",
"php-http/cache-plugin": "^1.7",
"php-http/curl-client": "^2.1",
"php-http/httplug-bundle": "^1.17",
"rbdwllr/reallysimplejwt": "^2.1",
"symfony/dependency-injection": "^4.4 || ^5.4 || ^6.0",
"symfony/framework-bundle": "^4.4 || ^5.4 || ^6.0",
"symfony/security-bundle": "^4.4 || ^5.4 || ^6.0",
"symfony/security-core": "^4.4 || ^5.4 || ^6.0",
"symfony/security-http": "^4.4 || ^5.4 || ^6.0",
"web-token/jwt-bundle": "^2.1",
"web-token/jwt-checker": "^2.1",
"web-token/jwt-core": "^2.1",
"web-token/jwt-key-mgmt": "^2.1",
"web-token/jwt-signature": "^2.1",
"web-token/jwt-signature-algorithm-hmac": "^2.1",
"web-token/jwt-signature-algorithm-rsa": "^2.1"
"stevenmaguire/oauth2-keycloak": "^5.1",
"symfony/dependency-injection": "^5.4 || ^6.4",
"symfony/framework-bundle": "^5.4 || ^6.4",
"symfony/security-bundle": "^5.4 || ^6.4",
"symfony/security-core": "^5.4 || ^6.4",
"symfony/security-http": "^5.4 || ^6.4"
},
"autoload": {
"psr-4": {
Expand Down
44 changes: 44 additions & 0 deletions src/Controller/LoginController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php declare(strict_types=1);

/*
* This file is part of the package t3g/symfony-keycloak-bundle.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/

namespace T3G\Bundle\Keycloak\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use T3G\Bundle\Keycloak\Service\RedirectService;

class LoginController extends AbstractController
{
private RedirectService $redirectService;

public function __construct(RedirectService $redirectService)
{
$this->redirectService = $redirectService;
}

public function login(): RedirectResponse
{
if (null !== $this->getUser()) {
return $this->redirectToRoute($this->getParameter('t3g_keycloak.routes.success'));
}

return $this->redirectService->generateLoginRedirectResponse(['openid', 'profile', 'roles', 'email']);
}

public function oauthCallback(): RedirectResponse
{
// fallback in case the authenticator does not redirect
return $this->redirectToRoute($this->getParameter('t3g_keycloak.routes.success'));
}

public function oauthLogout(): RedirectResponse
{
return $this->redirectService->generateLogoutRedirectResponse();
}
}
18 changes: 14 additions & 4 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ public function getConfigTreeBuilder(): TreeBuilder
->children()
->arrayNode('keycloak')->addDefaultsIfNotSet()
->children()
->scalarNode('jku_url')
->defaultValue('https://login.typo3.com/realms/TYPO3/protocol/openid-connect/certs')
->cannotBeEmpty()
->end()
->scalarNode('user_provider_class')
->defaultValue(KeyCloakUserProvider::class)
->cannotBeEmpty()
Expand All @@ -40,8 +36,22 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultValue([])
->scalarPrototype()->end()
->end()
->scalarNode('clientId')
->defaultValue('%env(KEYCLOAK_CLIENT_ID)%')
->cannotBeEmpty()
->end()
->end()
->end()
->arrayNode('routes')->addDefaultsIfNotSet()
->children()
->scalarNode('authentication')
->defaultValue('t3g_keycloak_oauthCallback')
->end()
->scalarNode('success')
->defaultValue('home')
->end()
->end()
->end()
->end()
;

Expand Down
48 changes: 17 additions & 31 deletions src/DependencyInjection/T3GKeycloakExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,28 @@ public function prepend(ContainerBuilder $container): void
$configs = $container->getExtensionConfig($this->getAlias());
$config = $this->processConfiguration(new Configuration(), $configs);

$container->setParameter('t3g_keycloak.keycloak.jku_url', $config['keycloak']['jku_url']);
$container->setParameter('t3g_keycloak.keycloak.user_provider_class', $config['keycloak']['user_provider_class']);
$container->setParameter('t3g_keycloak.keycloak.default_roles', $config['keycloak']['default_roles']);
$container->setParameter('t3g_keycloak.keycloak.role_mapping', $config['keycloak']['role_mapping']);
$container->setParameter('t3g_keycloak.keycloak.clientId', $config['keycloak']['clientId']);
$container->setParameter('t3g_keycloak.routes.authentication', $config['routes']['authentication']);
$container->setParameter('t3g_keycloak.routes.success', $config['routes']['success']);

if ($container->hasExtension($this->getAlias())) {
$container->prependExtensionConfig($this->getAlias(), ['keycloak' => []]);
$container->prependExtensionConfig($this->getAlias(), ['keycloak' => [], 'routes' => []]);
}

if ($container->hasExtension('knpu_oauth2_client')) {
$container->prependExtensionConfig(
'knpu_oauth2_client',
[
'clients' => [
'keycloak' => [
'redirect_route' => '%t3g_keycloak.routes.authentication%',
],
],
]
);
}

if ($container->hasExtension('httplug')) {
Expand Down Expand Up @@ -78,34 +93,5 @@ public function prepend(ContainerBuilder $container): void
]
);
}

if ($container->hasExtension('jose')) {
$container->prependExtensionConfig(
'jose',
[
'key_sets' => [
'login_typo3_com' => [
'jku' => [
'url' => '%t3g_keycloak.keycloak.jku_url%',
'is_public' => true
]
]
],
'jws' => [
'verifiers' => [
'login_typo3_com' => [
'signature_algorithms' => ['HS256', 'RS256'],
'is_public' => true
]
]
],
'jku_factory' => [
'enabled' => 'test' !== $_SERVER['APP_ENV'], // we don't want to have requests to the login server in test context
'client' => 'httplug.client.login_typo3_com',
'request_factory' => 'httplug.message_factory'
]
]
);
}
}
}
Loading

0 comments on commit e326265

Please sign in to comment.