Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TASK] Symfony 6 Upgrade #13

Merged
merged 15 commits into from
Sep 9, 2024
Merged
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
Loading