Skip to main content
Version: Next

Configuration

Configure OpenID Connect providers in System > User & Roles > OpenId Connect > OpenId Connect Configuration in Pimcore Studio, or directly in a Symfony configuration file (see Configuration Storage). Opening this screen requires the OpenID Connect Configuration permission, see Installation.

OpenID Connect Configuration screen in Pimcore Studio, showing a provider named Onelogin with its client ID, masked client secret, discovery URL, scopes, the two toggles, a collapsed Claim Mapping section, and the Default Provider select belowOpenID Connect Configuration screen in Pimcore Studio, showing a provider named Onelogin with its client ID, masked client secret, discovery URL, scopes, the two toggles, a collapsed Claim Mapping section, and the Default Provider select belowOpenID Connect Configuration screen in Pimcore Studio, showing a provider named Onelogin with its client ID, masked client secret, discovery URL, scopes, the two toggles, a collapsed Claim Mapping section, and the Default Provider select below

Provider Configuration​

Configure one or more OpenID Connect providers in parallel. Pimcore Studio shows a "Login with <Provider>" button per configured provider on its login page; clicking one starts that provider's OpenID Connect flow. Each provider needs a unique name.

On the provider side, register an application for Pimcore with:

  • Redirect URL: https://<YOUR_PIMCORE_DOMAIN>/pimcore-studio/api/bundle/openid-connect/auth/endpoint
  • Allowed scopes: openid profile email groups (see scopes below). Providers that reject unknown scopes, such as Microsoft Entra ID, need groups removed from Pimcore's scopes option; see the note there.

Once the application is set up, configure these required values per provider in Pimcore:

  • client_id: Client ID provided by the provider.
  • client_secret: Client secret provided by the provider. The configuration screen treats it as write-only: once saved, the value is never sent back to the browser and the field shows a placeholder instead. Leave the field empty to keep the stored secret, or enter a new value to replace it. Renaming a provider requires entering its secret again, because the stored secret is looked up by provider name.
  • url_discovery: Endpoint for OpenID configuration discovery, based on the OpenID Connect Discovery spec. Typically something like <PROVIDER_DOMAIN>/.well-known/openid-configuration. Some providers publish different signing keys depending on the application, for example Microsoft Entra ID with a custom signing key, where the key is only listed in the application-scoped discovery document (.../.well-known/openid-configuration?appid=<CLIENT_ID>). Use that URL here if login fails with idToken could not be verified and the kid of the token is missing from the listed kids. The error message names the kid and alg of the token, the kids of the key set and the jwks_uri that was used (the key must be in the key set the discovery document points to). The key set is cached for one day: after a key rotation, clear the cache tag oidc to see the current keys.

Optional values per provider:

  • scopes: Scopes sent with the authorization request. Defaults to openid, profile, email and groups. Pimcore always adds openid, even if you remove it, because the OpenID Connect flow requires it.

    note

    groups is not a standard OpenID Connect scope. Providers that reject unknown scopes, such as Microsoft Entra ID (error AADSTS70011), fail the login with the default list. For those providers, set scopes explicitly without groups, for example openid, profile and email. In the Studio provider form, remove the groups tag from the Scopes field. Entra ID delivers group claims through the group claims setting of the app registration instead of a scope.

    Pimcore matches roles by group name, but Entra ID emits group IDs (GUIDs) by default. Configure the app registration to emit group names, or use app roles and set claim_mapping groups to roles. Otherwise no role matches, and unless dont_overwrite_roles is enabled the user's Pimcore roles are removed on each login. Entra ID also omits the groups claim for users in more than about 200 groups (overage).

  • load_user_info: Merge the provider's userinfo response into the claims taken from the ID token, with the userinfo values winning. Enable this if the ID token alone does not carry all the claims Pimcore needs.

  • dont_overwrite_roles: Skip role re-assignment after login, so you can manage roles in Pimcore instead of the provider. See Role Mapping.

  • claim_mapping: Custom claim names, for providers that deviate from the OpenID Connect standard names. Maps the supported claims preferred_username (the username), given_name, family_name, email, groups (an array, or a comma- or semicolon-separated string, of group names), picture (URL of the user's avatar) and sub (the provider's remote user ID).

Default Provider​

Optionally set a default provider by name. Pimcore Studio's login page then redirects to that provider's login immediately instead of showing the local credentials form, as long as the browser has no Studio session yet. A user who is already signed in and opens the login page is taken into Studio without another round trip to the provider.

If a sign-in attempt fails, for example because the provider reports an error or Pimcore rejects the user, the browser returns to the login page with an error message, the credentials form and the provider buttons. The redirect does not start again by itself; the user decides whether to try again. Each failed attempt is written to the Pimcore log.

warning

The redirect happens as soon as the login page loads for a visitor without a Studio session. The local credentials form only appears after a sign-in attempt has failed, so local accounts cannot count on reaching it. If the default provider becomes unreachable, or fails during the code exchange (for example because the client secret was rotated at the provider, see Studio Login Flow), and locks out local accounts, remove PimcoreOpenIdConnectBundle::class from config/bundles.php and clear the cache to restore the plain login form. This works regardless of where the configuration is stored. If it is stored as symfony-config, removing default_provider from the configuration file (see Configuration Storage) works too and does not require disabling the bundle.

Studio Login Flow​

Pimcore Studio login page with username and password fields and a &quot;Login with Onelogin&quot; button below themPimcore Studio login page with username and password fields and a &quot;Login with Onelogin&quot; button below themPimcore Studio login page with username and password fields and a &quot;Login with Onelogin&quot; button below them

Once at least one provider is configured, a user signs in like this:

  1. Pimcore Studio's login page shows a "Login with <Provider>" button for each configured provider, next to the local credentials form (or redirects immediately if a default provider is set).
  2. Clicking a button sends the browser to the bundle's public callback route, the same Redirect URL you registered with the provider above, with the provider name attached. The route redirects to that provider's authorization endpoint, starting the OAuth2 authorization code flow.
  3. The user authenticates with the provider.
  4. The provider redirects back to the same callback route with an authorization code. The bundle validates the OAuth2 state and redirects the browser to its login route, passing the code along.
  5. Pimcore's security layer picks up that request with its OpenIdConnectAuthenticator. It exchanges the code for tokens, validates the ID token's signature and claims, and creates or updates the matching Pimcore user from the token claims (see Technical Details).
  6. The login route redirects the browser into Pimcore Studio, restoring the perspective and page that were active before the login started. A sign-in started on the login page itself lands on Studio's start page.

If the attempt fails before the code exchange (for example the provider reports an error or the OAuth2 state does not match), or Pimcore rejects the user, the browser lands on the Studio login page with an error message instead. An error during the code exchange or the ID token validation in step 5, for example a wrong client secret, ends on an HTTP 500 error page; the Pimcore log has the cause.

The local credentials form keeps working alongside SSO, unless a default provider forces the redirect described above.

Configuration Storage​

The configuration screen stores its data through a LocationAwareConfigRepository. Configure the storage location in the Symfony configuration tree:

  • symfony-config: write configuration as YAML to /var/config/oidc/pimcore_open_id_connect.yaml.
  • settings-store: write configuration to the Pimcore SettingsStore.
  • disabled: do not allow writes. The configuration screen becomes read-only, and its Save button and input fields are disabled.

See the Pimcore Configuration Storage Locations and Fallbacks documentation for the underlying mechanism.

Example: Custom Storage Directory​

pimcore_open_id_connect:
config_location:
open_id_connect:
write_target:
type: 'symfony-config'
options:
directory: '/var/www/html/var/config/oidc'

Example: Providers Defined in Symfony Configuration​

Define providers directly in a Symfony configuration file instead of using the configuration screen. In this case, the configuration screen becomes read-only, since the values it would edit no longer come from a writable source. The client secret is shown as stored but never displayed, and it can reference an environment variable through %env(OIDC_CLIENT_SECRET)%, which keeps it out of the database and the configuration file.

pimcore_open_id_connect:
default_provider: onelogin

providers:
onelogin:
client_id: <CLIENT_ID>
client_secret: <CLIENT_SECRET>
url_discovery: https://<USERNAME>.onelogin.com/oidc/2/.well-known/openid-configuration
okta:
client_id: <CLIENT_ID>
client_secret: <CLIENT_SECRET>
url_discovery: https://<USERNAME>.okta.com/.well-known/openid-configuration
load_user_info: true
dont_overwrite_roles: false
scopes:
- openid
- profile
- email
- groups
claim_mapping:
preferred_username: preferred_username
given_name: given_name
family_name: family_name
email: email
groups: groups
picture: picture
sub: sub

Debugging​

Open System > User & Roles > OpenId Connect > Debugging Tool in Pimcore Studio (same permission as the configuration screen) to troubleshoot a provider setup. It opens in a new browser tab and lists the configured providers.

Picking a provider runs a real sign-in against it, the same OAuth2 flow described above, but instead of logging you into Pimcore Studio, the tool shows the raw response: the ID token claims, the userinfo response, the configured claim_mapping, and the resulting merged user information Pimcore would use. Use it to verify a provider sends the claims your claim_mapping expects. If the flow fails, the tool renders the error message instead.