Install the Package
composer require galillei/ssobundle
Copy Configuration Files
src/config/sso_fp.yaml → config/routes/sso_fp.yamlsrc/config/knpu_oauth2_client.yaml → config/packages/knpu_oauth2_client.yamlsecurity.yaml with the provided providers, firewalls, and access_control rules.Environment Variables
Add to .env:
OAUTH_FACTORY_PORTAL_ID=your_client_id
OAUTH_FACTORY_PORTAL_SECRET=your_client_secret
Register Services
Update config/services.yaml with the provided FactoryOauth2ClientProvider and app.factory.provider aliases.
Run Migrations (if applicable)
Check for database migrations in src/Migrations/ and publish them if needed:
php bin/console make:migration
php bin/console doctrine:migrations:migrate
First Use Case: OAuth Login
<a href="{{ path('connect_factoryportal_start') }}">Login with Factory Portal</a>
/connect/factoryportal./connect/factoryportal (route: connect_factoryportal_start)./connect/factoryportal/check.FactoryPortalUserProvider loads or creates a user based on the OAuth response.
// Example: Manually trigger OAuth login in a controller
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
public function login(UrlGeneratorInterface $urlGenerator): RedirectResponse
{
return $this->redirect($urlGenerator->generate('connect_factoryportal_start'));
}
Override the default user provider to map OAuth attributes to your User entity:
# config/services.yaml
SSO\FpBundle\Provider\FactoryPortalUserProvider:
arguments:
$userClass: App\Entity\CustomUser
$attributeToPropertyMap:
email: email
first_name: firstName
last_name: lastName
# Add custom mappings as needed
Extend the authenticator to run logic after successful login:
use SSO\FpBundle\Security\FactoryPortalAuthenticator;
class CustomFactoryPortalAuthenticator extends FactoryPortalAuthenticator
{
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
$user = $token->getUser();
// Add custom logic (e.g., log activity, assign roles)
return parent::onAuthenticationSuccess($request, $token, $firewallName);
}
}
Update security.yaml to use your custom authenticator:
custom_authenticators:
- App\Security\CustomFactoryPortalAuthenticator
Redirect users to the Factory Portal logout endpoint:
<a href="{{ path('app_logout') }}">Logout</a>
The app_logout route triggers a logout from both your app and the Factory Portal (if configured).
The bundle relies on knpuniversity/oauth2-client-bundle. Customize OAuth clients in config/packages/knpu_oauth2_client.yaml:
clients:
factory_portal:
type: oauth2
client_id: '%env(OAUTH_FACTORY_PORTAL_ID)%'
client_secret: '%env(OAUTH_FACTORY_PORTAL_SECRET)%'
provider: factory_portal
scopes: 'email profile'
options:
authorization_options:
scope: { value: 'email profile' }
Use the IS_AUTHENTICATED_FULLY rule to protect routes after OAuth login. For granular control, extend the access_control section:
access_control:
- { path: ^/dashboard, roles: ROLE_USER }
- { path: ^/admin, roles: ROLE_ADMIN }
Use Symfony’s HATEAAS or manual testing to verify:
/connect/factoryportal triggers OAuth flow./connect/factoryportal/check creates/updates a user./app_logout clears sessions.OAUTH_FACTORY_PORTAL_ID or OAUTH_FACTORY_PORTAL_SECRET are missing..env and restart the server:
php bin/console cache:clear
app_user_provider in security.yaml doesn’t match the bundle’s provider, authentication fails.providers:
app_user_provider:
id: SSO\FpBundle\Provider\FactoryPortalUserProvider
connect_factoryportal_start. Conflicts may arise if you manually define similar routes.config/routes/sso_fp.yaml and update routes.yaml:
sso_fp:
resource: "@SSOFpBundle/Resources/config/routes.yaml"
prefix: /
/connect/factoryportal/check may fail with CSRF errors.security.yaml:
firewalls:
main:
# ...
form_login:
csrf_token_generator: security.csrf.token_manager
Add this to config/packages/knpu_oauth2_client.yaml to log OAuth responses:
clients:
factory_portal:
# ...
options:
logging: true
Temporarily add logging to the user provider:
// In FactoryPortalUserProvider
public function loadUserByOAuthUserResponse(OAuthUser $response)
{
$this->logger->debug('OAuth response:', ['response' => $response->toArray()]);
// ...
}
If users aren’t persisting, check:
User entity has the correct properties (e.g., email, firstName).prePersist, preUpdate) aren’t modifying the user unexpectedly.Extend the FactoryOauth2ClientProvider to fetch additional attributes:
use SSO\FpBundle\Provider\FactoryOauth2ClientProvider;
class CustomOauth2ClientProvider extends FactoryOauth2ClientProvider
{
public function getAdditionalParameters(): array
{
return [
'prompt' => 'consent',
'additional_params' => ['custom_param' => 'value'],
];
}
}
Register it in services.yaml:
SSO\FpBundle\Provider\FactoryOauth2ClientProvider:
class: App\Provider\CustomOauth2ClientProvider
Customize the redirect after login in the authenticator:
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
$targetPath = $this->getTargetPath($request->getSession(), new UrlGeneratorInterface());
return new RedirectResponse($targetPath ?: '/dashboard');
}
Reuse the bundle’s patterns to add support for other OAuth providers by:
*Authenticator class.FactoryPortalUserProvider for provider-specific logic.Hook into the bundle’s events to run logic before/after authentication:
use SSO\FpBundle\Event\FactoryPortalAuthEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
#[AsEventListener(event: 'factory_portal
How can I help you explore Laravel packages today?