diff --git a/README.md b/README.md index d2ae26f..7bd6c6b 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,10 @@ class HomeController extends AbstractController #[Route(path: '/login', name: 'login', methods: ['GET'])] public function login(ClientRegistry $clientRegistry): RedirectResponse { + if (null !== $this->getUser()) { + return $this->redirectToRoute('dashboard'); + } + return $clientRegistry ->getClient('keycloak') ->redirect([ @@ -86,7 +90,7 @@ class HomeController extends AbstractController } /** - * A callback route is required to authenticate the user. + * This route must match the authentication route in your bundle configuration. */ #[IsGranted('ROLE_USER')] #[Route(path: '/oauth/callback', name: 'oauth_callback', methods: ['GET'])] @@ -120,6 +124,11 @@ t3g_keycloak: # Defaults: - ROLE_USER - ROLE_OAUTH_USER + routes: + # redirect_route passed to keycloak + authentication: oauth_callback + # route to redirect to after successful authentication + success: dashboard ``` ### Role Mapping diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index ca8870f..96c30c6 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -38,6 +38,16 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->end() ->end() + ->arrayNode('routes')->addDefaultsIfNotSet() + ->children() + ->scalarNode('authentication') + ->defaultValue(null) + ->end() + ->scalarNode('success') + ->defaultValue(null) + ->end() + ->end() + ->end() ->end() ; diff --git a/src/DependencyInjection/T3GKeycloakExtension.php b/src/DependencyInjection/T3GKeycloakExtension.php index 838b0d1..b18229b 100644 --- a/src/DependencyInjection/T3GKeycloakExtension.php +++ b/src/DependencyInjection/T3GKeycloakExtension.php @@ -37,9 +37,11 @@ public function prepend(ContainerBuilder $container): void $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.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('httplug')) { diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml index ab2e3c0..aa433c6 100644 --- a/src/Resources/config/services.yaml +++ b/src/Resources/config/services.yaml @@ -15,6 +15,9 @@ services: T3G\Bundle\Keycloak\Security\KeyCloakAuthenticator: class: T3G\Bundle\Keycloak\Security\KeyCloakAuthenticator public: true + arguments: + $routeAuthentication: '%t3g_keycloak.routes.authentication%' + $routeSuccess: '%t3g_keycloak.routes.success%' T3G\Bundle\Keycloak\EventSubscriber\RequestSubscriber: tags: [ kernel.event_subscriber ] diff --git a/src/Security/KeyCloakAuthenticator.php b/src/Security/KeyCloakAuthenticator.php index 5911b21..74c48df 100644 --- a/src/Security/KeyCloakAuthenticator.php +++ b/src/Security/KeyCloakAuthenticator.php @@ -35,22 +35,25 @@ class KeyCloakAuthenticator extends OAuth2Authenticator implements Authenticatio private SessionInterface $session; private RouterInterface $router; private UserProviderInterface $userProvider; + private ?string $routeAuthentication; + private ?string $routeSuccess; /** * @param KeyCloakUserProvider $userProvider */ - public function __construct(ClientRegistry $clientRegistry, RequestStack $requestStack, RouterInterface $router, UserProviderInterface $userProvider) + public function __construct(ClientRegistry $clientRegistry, RequestStack $requestStack, RouterInterface $router, UserProviderInterface $userProvider, ?string $routeAuthentication = null, ?string $routeSuccess = null) { $this->client = $clientRegistry->getClient('keycloak'); $this->session = $requestStack->getSession(); $this->router = $router; $this->userProvider = $userProvider; + $this->routeAuthentication = $routeAuthentication; + $this->routeSuccess = $routeSuccess; } public function supports(Request $request): ?bool { - // @TODO: make configurable - return 'oauth_callback' === $request->attributes->get('_route'); + return $this->routeAuthentication === $request->attributes->get('_route'); } public function authenticate(Request $request): Passport @@ -76,20 +79,21 @@ public function authenticate(Request $request): Passport public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response { - // @TODO: make configurable + if (null === $this->routeSuccess) { + return null; + } + return new RedirectResponse( - $this->router->generate('dashboard'), + $this->router->generate($this->routeSuccess), Response::HTTP_TEMPORARY_REDIRECT ); } public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response { - // @TODO: make configurable - return new RedirectResponse( - $this->router->generate('login'), - Response::HTTP_TEMPORARY_REDIRECT - ); + $message = strtr($exception->getMessageKey(), $exception->getMessageData()); + + return new Response($message, Response::HTTP_FORBIDDEN); } /** @@ -98,11 +102,7 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio */ public function start(Request $request, AuthenticationException $authException = null): Response { - // @TODO: make configurable - return new RedirectResponse( - $this->router->generate('login'), - Response::HTTP_TEMPORARY_REDIRECT - ); + return new RedirectResponse('/', Response::HTTP_TEMPORARY_REDIRECT); } private function getScopesFromToken(AccessToken $token): array