A note from 2026: This article was published in 2016. The “hybris” product name has since been phased out in favor of SAP Commerce Cloud, and Cockpit Framework/HMC/Product Cockpit have been deprecated in favor of Backoffice; verify SAML SSO extension behavior against your current SAP Commerce Cloud version.

Situation

Okta is a cloud-based SSO platform that allows users to enter one name and password to access multiple applications. It also works as an identity provider, which is useful if you want to store credentials outside your service.

There are two user groups where SSO integration makes sense: business users and customers.

Complexity

Hybris OOTB doesn’t support any particular SSO providers. It has a module named samlsinglesignon, which can be used for integration with any SAML-compatible SSO service. However, this module is designed only for hybris Assisted Service Module functionality and belongs to the call center features.

Solution

The video below shows the results of this experiment.

In the video, Okta is an external identity provider: hybris login → “OKTA” button → OKTA.com form → Okta credentials → hybris e-shop, where the customer is authenticated.

Technical solution

Behind the scenes, the interaction between Okta and hybris looks like this:

  1. Once you try to access the protected resource, the system redirects you to the SSO entry point: the samlsinglesignon extension, /saml/.
  2. The SSO entry point generates a new authentication request using the SAML 2.0 protocol, digitally signs it, and sends it to Okta.
  3. After authentication at Okta with your account, you will be redirected back to hybris and automatically signed in.
  4. The samlsinglesignon extension listens to incoming requests (/samlsinglesignon/*). Once the extension receives a request from Okta, it checks whether the request has a correct SAML assertion. If it fails, the extension redirects the user back to the identity provider, Okta, and the user is asked to log in.
  5. Otherwise, it creates the secure cookie samlPassThroughToken and redirects the user to the URL of the protected resource. This cookie should be used to initiate the customer session by the website. The SSO functionality in hybris is preconfigured to work with the ASM module, so there is an asmaddon that has a filter that processes samlPassThroughToken and sets a session user if the token is found. We are not going to use ASM Addon in this solution, so we need to write our own processor that sets up the customer session based on the cookie from samlsinglesignon.

Okta SSO authentication flow for hybris

There are a number of edge cases that need to be supported in your code. For example, the IDP session may end earlier or later than the storefront session. In the “later” case, the storefront should request the token again and re-establish authentication seamlessly without any data loss. You don’t need to parse the token and authenticate the user if this user has already been authenticated. You also need to support single sign-out. User data provisioning is also needed if you use Okta as the IDP. If you use the external IDP for more than one customer type, you need to support different types of sessions.

Configuring Okta

Okta application in the Okta console

Create new app → SAML 2.0 → enter the app name, then specify two URLs:

  1. Single Sign on URL. Change your domain here: https://localhost:9002/samlsinglesignon/saml/SSO. It is very important to specify the correct domain and protocol here.

  2. Audience URI (SP Entity ID): urn:ssoextension:hybris:de or your own SP Entity ID. You can change it in the configuration. I used the default value.

  3. Download the certificate here:

    Download certificate in Okta

  4. Download metadata.xml using the “Identity Provider metadata” link:

    Identity Provider metadata link in Okta

    You will need to re-download it each time you change app settings. You need to restart hybris each time you replace metadata.xml.

  5. Create a sample user:

    Sample user in Okta

  6. Assign the app to the user. This operation could be done automatically later using the API, if needed.

Configuring the samlsinglesignon extension

keytool.exe -certreq -alias hybris -keystore samlKeystore.jks -file certificate.cer

Copy the downloaded metadata.xml into the security folder, or change sso.metadata.location to your own. Change the following parameters. I used the default values.

sso.metadata.location = classpath:security/metadata.xml
sso.entity.id = urn:ssoextension:hybris:de
sso.keystore.location = security/samlKeystore.jks
sso.keystore.password = changeit
sso.keystore.privatekey.password = changeit
sso.keystore.default.certificate.alias = hybris
sso.keystore.privatekey.alias = hybris

Token processor

For ASM, you don’t need to do anything: token processing has already been implemented in AssistedServiceFilter.java:

protected void doFilterInternal(final HttpServletRequest httpservletrequest, final HttpServletResponse httpservletresponse,
        final FilterChain filterchain) throws ServletException, IOException
{
    if (AssistedServiceUtils.getSamlCookie(httpservletrequest) != null)
    {
        try
        {
            final LoginToken token = new CookieBasedLoginToken(AssistedServiceUtils.getSamlCookie(httpservletrequest));
            // perform login only in case token doesn't belong to currently logged in agent
            if (!getAssistedServiceFacade().isAssistedServiceAgentLoggedIn()
                    || !getAssistedServiceFacade().getAsmSession().getAgent().getUid().equals(token.getUser().getUid()))
            {
                if (getAssistedServiceFacade().isAssistedServiceAgentLoggedIn())
                {
                    getAssistedServiceFacade().logoutAssistedServiceAgent();
                }
                getAssistedServiceFacade().loginAssistedServiceAgent(httpservletrequest);
                getAssistedServiceAgentLoginStrategy().login(token.getUser().getUid(), httpservletrequest, httpservletresponse);
                getAssistedServiceFacade().emulateAfterLogin();
            }
        }
        ...

For customers and cockpit administrators, you need to set the session manually:

....
final UserModel user = userService.getUserForUID(token.getUser().getUid());
....

Create a filter in the storefront extension that will check whether the cookie is created and start the session by getting the user from the cookie.

Storefront filter configuration for SAML token processing

Note: This filter should be defined last in the storefront filter chain, or after springSecurityFilterChain, so that it gets called after jsessionid is created.

© Rauf Aliev, June 2016