Search by

dmlab / module-customer-sso

dmlab

Storefront SSO capability for Magento 2 — provider-agnostic OIDC login for customers (JIT customer creation, account linking by email/sub, IdP-claim to customer-group mapping).

Package info

github.com/dmlab-work/module-customer-sso

Type:magento2-module

pkg:composer/dmlab/module-customer-sso

Statistics

Installs: 31

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

0.2.5 2026-10-30 21:54 UTC

This package is auto-updated.

Last update: 2026-10-30 21:57:08 UTC


README

Provider-agnostic single sign-on for the Magento 2 storefront (OIDC).

CI codecov Packagist Version Downloads PHP License Magento

Shoppers sign in with the account they already have at your identity provider (Okta via customer-sso-okta) instead of creating another password. The first sign-in creates the customer, existing customers are linked by verified email, and IdP groups can set the customer group (e.g. wholesale).

Customer SSO settings in Magento: enable, identity provider, client ID, password login and account linking

Install

Usually installed via a provider plugin, which pulls this module and sso-core:

composer require dmlab/module-customer-sso-okta
bin/magento module:enable DmLab_CustomerSsoOkta DmLab_CustomerSso DmLab_SsoCore
bin/magento setup:upgrade

Direct install of the core alone:

composer require dmlab/module-customer-sso
bin/magento module:enable DmLab_SsoCore DmLab_CustomerSso
bin/magento setup:upgrade

Register the module callback URL in your IdP: https://<store-host>/customersso/sso/callback. It must exactly match the storefront URL used at runtime.

Requirements

  • Magento 2.4.7+ · PHP 8.2–8.5
  • A provider plugin, e.g. dmlab/module-customer-sso-okta
  • dmlab/module-sso-core ^0.2.3 (installed automatically)
  • The store's callback URL registered at the IdP

Hyvä

A Hyvä (Tailwind) template for the login-page button ships with the module, but the theme layout must be edited by hand. In the Hyvä theme's Magento_Customer/layout/customer_account_login.xml:

<referenceBlock name="dmlab.customer.sso.button" template="DmLab_CustomerSso::login/sso-button-hyva.phtml"/>

The checkout and minicart popup buttons are Luma only.

Pairs with customer-sso-okta (Okta sign-in) and customer-passkey (passkey sign-in).

Configuration

Admin → Stores → Configuration → DMLab → Customer SSO → General (config path dmlab_customer_sso/general/*). Settings are store-scoped, so SSO can be enabled and tuned per store view.

Field Path Notes
Enable Customer SSO enabled Master switch; off by default.
Identity Provider active_provider Dropdown populated by installed provider plugins.
Client ID client_id OIDC client id from the IdP.
Client Secret client_secret Stored encrypted; sensitive, so app:config:dump leaves it out — set it per environment.
Keep Password Login allow_password_login On (default): native email/password login stays available alongside SSO. Off: once SSO is live, login is SSO-only — the form is hidden and password login is refused server-side (login form, checkout popup, REST and GraphQL customer tokens).
Account Linking by Email auto_link_policy require_verification (default) or disabled. See below.
Group to Customer-Group Map group_customer_group_map IdP group → customer-group rules. See below.
Sign Out of IdP on Logout idp_logout Off by default. See below.

The "Sign in with SSO" button appears on the customer login page and in the Luma checkout login popups (authentication popup and the checkout authentication step) when the module is enabled and a provider is selected; it uses the identity provider's branding. Popup sign-in returns the shopper to checkout. Custom placements can link to customersso/sso/start?referer=<base64 URL> to return to that page; a URL off the store's own origin is ignored. Setting Keep Password Login to No hides the native form and refuses password login once SSO is live. As a break-glass, password login stays available on an unconfigured or broken install (no active provider), so a mis-set toggle can never lock shoppers out.

Account linking

An SSO identity is matched to a customer in this order:

  1. By IdP identity — issuer (iss) + subject (sub) stored in dmlab_customer_sso_subject per provider. Signs in regardless of email verification. A link created before issuers were stored is bound to the issuer of its next matching login.

  2. By email, governed by auto_link_policy:

    • require_verification (default) — adopt the existing customer only when the IdP marks the email verified (email_verified) and the account is not awaiting email confirmation. Legacy auto resolves to this.
    • disabled — never link by email.

    Otherwise the login is refused and the shopper is told to sign in with their password and link from My Account — keep Keep Password Login on if existing customers may need this path.

  3. JIT create — no match → a new customer is created only when the IdP marks the email verified; an unverified email is refused and nothing is created.

Explicit linking — a signed-in customer links or unlinks an identity under My Account → Single Sign-On (customersso/account). The session already proves ownership, so the verified flag is not checked; the link is bound to the session customer. A customer holds at most one identity per provider. An identity belongs to one customer — one per website when customer accounts are shared per website (customer/account_share/scope).

Group → customer-group mapping

group_customer_group_map takes one rule per line as idp_group=customer_group_id, where customer_group_id is a Magento customer_group id. Lines are in priority order: a customer holds one group, so the first line matching any of the identity's groups wins, and a duplicate group keeps its first line. Blank lines and # comments are ignored.

# IdP group          Customer group id
wholesale=2
vip=3

With no rules configured this is inert: customer groups are never touched, so a store using SSO only for login keeps its manually assigned groups. Once a map exists, groups are resolved on JIT create and refreshed on every login, so IdP group changes take effect at next sign-in. An identity whose groups match no rule reverts to the store's default customer group (GroupManagementInterface::getDefaultGroup) — customers always hold a valid group. A rule pointing at a non-existent group id is skipped, leaving the current group unchanged. When the IdP marks the groups claim as distributed (groups overage, e.g. Entra _claim_names), the token's groups are incomplete and the current group is left unchanged.

IdP logout

With Sign Out of IdP on Logout on, a shopper who signed in with SSO is also signed out of the IdP (OIDC RP-Initiated Logout 1.0): after the local logout the browser goes to the IdP's end_session_endpoint with id_token_hint (the login's ID token, kept in the customer session), client_id and post_logout_redirect_uri, then returns to the logout success page. This ends the shopper's IdP session for every app using it.

Register https://<store-host>/customer/account/logoutSuccess/ (each store base URL) as a post-logout redirect URI at the IdP. If the IdP advertises no end_session_endpoint, discovery fails, the store's active provider changed since login, or the shopper signed in with a password, logout stays local.

Architecture

This module is the storefront-login capability core: it signs shoppers in over OIDC via sso-core but never references a concrete IdP. A provider plugin (e.g. customer-sso-okta) registers a preset that binds it to an identity provider.

  1. Shopper clicks "Sign in with SSO" → customersso/sso/start builds the OIDC auth URL (state + nonce + PKCE) via sso-core and the active preset, persists the state and a login intent (optional own-origin return URL) in the customer session (valid 10 minutes, at most 10 pending per session), then redirects to the IdP. Linking starts the same way from customersso/account/link (POST, signed-in only) with a link intent.
  2. IdP redirects back to customersso/sso/callback, which validates state and the RFC 9207 iss response parameter, exchanges the code, and normalizes claims into an Identity via sso-core. Failures return with a message to the login page, or to My Account → Single Sign-On for a link intent.
  3. login (refused when a customer is already signed in): the customer is matched (issuer + sub → verified email under policy → verified JIT create), the group is resolved, the session is established and mage-cache-sessid is reset so private content reloads; redirect to the return URL or My Account.
  4. link: the identity is linked to the session customer; redirect to My Account → Single Sign-On.

License

OSL-3.0 © DMLab. Commercial licensing and support: https://dmlab.work.