This bundle provides single-sign on support for Pimcore backend login. This allows to maintain user credentials and roles on external authenticatin providers.
Delegate user management to an authentication provider has a lot of advantages:
- user only has to remember one password for all used services
- encryption and security is expected to be higher on those authentication providers as their whole business model highly depends on it
- administration has a single system where they can create users - so nobody has to create Pimcore accounts manually
- administration has a single system to disable users - when an employee leaves a company, you can disable all logins with a single click
Currently the bundle supports OpenID, SAML and LDAP authentication providers. Support for OAuth2 will come soon.
OpenID is supported by a wide range of applications like
- Microsoft Azure Active Directory / Entra ID
- Auth0
- Okta
- and others
You can buy this plugin in the Blackbit Shop or write an email to [email protected].
Configuration can be done directly in Pimcore backend under Settings > Users / Roles > Single Sign-on Configuration:
The bundle gets shipped with detailed instructions how to set up auth applications at the authentication provider, where to find the necessary keys / settings and where to paste those secrets in Pimcore.
You can add as many auth providers as you want (e.g. if your internal users use a different auth provider as your Pimcore agency).
You can also configure default roles for each authentication provider. Those rules will get applied to newly created users. If an existing user logs in the default roles will not get applied.
For each authentication provider (except for LDAP providers) a new button will be added to Pimcore's login screen:
After the user clicks this button, he will get redirected to the authentication provider. There he can log in (or perhaps already is logged in). Afterwards he will get redirected to your Pimcore and logged in. Internally a usual Pimcore user will get created based on the information of the authentication provider (e.g. username, email, roles).
On the auth provider site you have you create an application with https://your-pimcore.com/sso/redirect
as callback URL. The remaining configuration settings depend on the used auth provider.
Information about OpenID configuration for certain auth providers:
To use Azure AD as authentication provider, you have to create a new Azure AD app:
- Log in to your Azure account and navigate to Azure Active Directory > App registrations.
- Select
+ New registration
to create a new app. - Enter a name of your choice in the
Name
field. - Set
Redirect URI
to https://your-pimcore.com/sso/redirect - please replace the domain name to your real one. - Click
Register
- Copy the
Application (client) ID
from the app configuration page and paste it in the Pimcore SSO configuration's fieldClient ID
. - Navigate to the app’s configuration page. If you just completed the previous step, you should already be on this page. Otherwise, search for your app name in the App registrations list.
- Select
Certificates & secrets
. - Select
+ New client secret
. Provide a description and an expiration length that follows your security organization’s guidelines. Then click Add. - Copy the newly-created client secret and paste it in the Pimcore SSO configuration's field
Client Secret
. - In Pimcore SSO configuration, as
Discovery URL
enter https://login.microsoftonline.com/[TENANT]/.well-known/openid-configuration - please replace[TENANT]
with your tenant id. - In Pimcore SSO configuration, as
Scopes
useopenid
,profile
,email
(and optionallygroups
if you want to map Azure AD / Entra ID groups to Pimcore roles) - In user field mappings assign:
Pimcore field | Azure AD field |
---|---|
Username / login | unique_name |
Given name | given_name |
Family name | family_name |
unique_name | |
Groups / Roles | groups |
If you are not sure what to enter, please write an email to [email protected].
After configuration there will be an additional button on the Pimcore login page. This can be used to authenticate on the auth provider site and then be redirected and logged in to Pimcore.
If you choose a Default Provider
you will automatically get redirected to the auth provider's login page when you access https://your-pimcore.com/admin
.
For LDAP authentication providers no additional button gets added to the login screen but the normal login form gets used. With those credentials the LDAP provider gets requested and if the credentials are valid, the user gets logged in. Same as for other authentication types internally a usual Pimcore user will get created and the LDAP profile fields get applied ( e.g. username, email).
When using LDAP as authentication provider, you have to configure
Base DN
: Base DN for the directory (example: dc=example,dc=com).Search DN
: (Read-only) user's DN, which will be used to authenticate against the LDAP server in order to fetch the user's information (example: cn=your_search_dn_user,ou=users,dc=example,dc=com).
To log in via SAML you need to configure:
Entity ID
ACS URL
X509 Certificate
You can map the fields which get provided by the configured authentication providers to update the corresponding Pimcore user's account data, for example to keep email address up-to-date or to assign roles.
Mapped Groups / Roles
will automatically be assigned as roles to the just logged-in user. Non-existing roles will automatically get created (at first without any permissions).
In addition, you can configure Default roles
. These roles will automatically be assigned to newly created users. They do not get applied to already existing users.
You can configure one authentication provider to be the default one. When this is done, requests for Pimcore backend https://your-pimcore.com/admin
will automatically get redirected to the authentication provider to login there. Afterwards the user will get sent back to Pimcore backend being logged in.
The sso.logged-in
event gets triggered on successful login. The following event arguments get provided:
user
: The found / created\Pimcore\Model\User
objectdata
: Associative array with all data which got returned from authentication providersavePimcoreUser
: boolean value to define if the Pimcore user should get saved (default: true)provider
: The name of the used SSO provider (as configured in Pimcore backend)
(The following instructions are only important if you want to add SSO to your Pimcore-based frontend application (= website). If you only want to log in to Pimcore backend, the following section can be ignored.)
To integrate single sign-on in frontend applications, you can add the following code in your Twig templates:
{{
render(controller(
'Blackbit\\SingleSignOnBundle\\Controller\\IdentityController:frontendProvidersAction'
))
}}
If you want to get auth provider data as JSON, please use json
parameter with value true
. If json
not provided, buttons will be shown as html.
{% set authProviders %}
{{
render(controller(
'Blackbit\\SingleSignOnBundle\\Controller\\IdentityController:frontendProvidersAction',
{ 'json': true }
))
}}
{% endset %}
window.location.href = {{ path('sso_frontend_redirect', {'provider': authProviders[0].name }) }};
Furthermore, you can set redirectUrl
parameter to redirect user after successful login. If redirectUrl
is not provided, the user will get redirected to the requested page - if this is not available (because the login page was called without referer), it will redirect to default URL /
(start page).
{{
render(controller(
'Blackbit\\SingleSignOnBundle\\Controller\\IdentityController:frontendProvidersAction',
{ 'json': false, 'redirectUrl': '/en/test' }
))
}}
You can change the HTML output by overriding the @BlackbitSingleSignOn/frontend_button.html.twig
template - for example copy the following code to <Pimcore root folder/templates/bundles/BlackbitSingleSignOn/frontend_button.html.twig
:
<div id="sso-button-container" class="sso-button-container">
{% for provider in providers %}
<form action="{{ path('sso_frontend_redirect') }}" method="GET">
{% if provider.type != "ldap" %}
<input type="hidden" name="provider" value="{{ provider.name }}" />
<button class="sso-button">{% if provider.icon %}<img src="{{ provider.icon }}"> {% endif %}{{ provider.name | trans({}, 'admin') }}</button>
{% else %}
<input type="text" name="username" autocomplete="username" placeholder="{{ 'username'|trans([], 'admin') }}" required autofocus>
<input type="password" name="password" autocomplete="current-password" placeholder="{{ 'password'|trans([], 'admin') }}" required>
<input type="hidden" name="csrfToken" id="csrfToken" value="{{ pimcore_csrf.getCsrfToken() }}">
<button type="submit">{{ 'login'|trans([], 'admin') }}</button>
{% endif %}
</form>
{% endfor %}
</div>
and adjust it to your needs.
You can subscribe to the event sso.logged-in
which gets triggered on a successful login.
For example, in services.yaml
register your event subscriber
App\EventListener\SsoLoginListener:
tags:
- { name: kernel.event_listener, event: sso.logged-in, method: onSuccessLogin }
Then create SsoLoginListener
class in src\EventListener
folder with following code:
namespace App\EventListener;
use Pimcore\Model\User;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
class SsoLoginListener {
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage) {
$this->tokenStorage = $tokenStorage;
}
public function onSuccessLogin (GenericEvent $e) {
/** @var User $user */
$user = $e->getArgument('user');
// change user data
$user->setEmail('[email protected]');
// or even use a user object of a different class
$user = new \Pimcore\Model\DataObject\CustomUser();
$user->setUsername($user->getUsername());
$user->setPassword($user->getPassword()); // this is a random one-time password which gets reset on every login
// log user in
$token = new UsernamePasswordToken($user, 'frontend_firewall_name', $user->getRoles());
$this->tokenStorage->setToken($token);
}
}
To check if a user is logged in, you can use the SingleSignOnTrait
in your controller:
class MyController {
use \Blackbit\SingleSignOnBundle\Controller\SingleSignOnTrait;
public function myAction(\Symfony\Component\HttpFoundation\Request $request) {
try {
$this->guardLoggedIn($request);
} catch(\Exception $e) {
return $this->redirectToRoute('login'); // customize the route name for the login page here
}
}
}
For logout you can use the SingleSignOnTrait
:
class MyController {
use \Blackbit\SingleSignOnBundle\Controller\SingleSignOnTrait;
public function logoutAction(\Symfony\Component\HttpFoundation\Request $request) {
$this->logout($request);
return $this->redirectToRoute('login'); // customize the route name for the logout page here
}
}