Search code examples
springhttp-redirectsap-commerce-cloud

How can I redirect a user after successful login to different pages, based on their previous page?


I'm redirecting a user to the homepage with the "Default target-url" being set to "/". However, I need to redirect a user if they login on either a product page (/p/) or a search page (/search). How could I go about doing this? I'm not all that knowledgeable about Spring Security and redirects yet.

I've tried intercepting the request within the onAuthenticationSuccess() method in my AuthenticationSuccessHandler and checking for the URL if it contains the product page or search page url.

Within the AuthenticationSuccessHandler:

if (!response.isCommitted()) {
   super.onAuthenticationSuccess(request,response,authentication);
}

Within the spring-security-config.xml:

<bean id="authenticationSuccessHandler" class ="com.storefront.AuthenticationSuccessHandler" scope="tenant">
<property name="rememberMeCookieStrategy" ref="rememberMeCookieStrategy" />
<property name="customerFacade" ref="customerFacade" />
<property name="sCustomerFacade" ref="sCustomerFacade" />
<property name="sProductFacade" ref="sProductFacade" />
<property name="defaultTargetUrl" value="/" />
<property name="useReferer" value="true" />
<property name="requestCache" value="httpSessionRequestCache" />

The expected results will be:

  1. When a user logs in on a product page, they will be returned to the product page they were on.
  2. When a user logs in on a search page, they will be returned to the search page they were on.
  3. If the user logs in while not on a product or search page, they are redirected to the homepage.

Solution

  • Hybris OOTB (I'm referring to V6.7) has a functionality where you can list the URLs for which you want to redirect to Default Target Url. The idea here is to have another list(or replace the existing one) with the reverse logic which only allows the given URLs and redirects all other URLs to the default target URLs.

    In OOTB you can see listRedirectUrlsForceDefaultTarget in the spring-security-config.xml, where can define the list of URLs which you want to redirect to the default target. Like below.

    <alias name="defaultLoginAuthenticationSuccessHandler" alias="loginAuthenticationSuccessHandler"/>
    <bean id="defaultLoginAuthenticationSuccessHandler" class="de.hybris.platform.acceleratorstorefrontcommons.security.StorefrontAuthenticationSuccessHandler" >
        <property name="customerFacade" ref="customerFacade" />
        <property name="defaultTargetUrl" value="#{'responsive' == '${commerceservices.default.desktop.ui.experience}' ? '/' : '/my-account'}"/>
        <property name="useReferer" value="true"/>
        <property name="requestCache" ref="httpSessionRequestCache" />
        <property name="uiExperienceService" ref="uiExperienceService"/>
        <property name="cartFacade" ref="cartFacade"/>
        <property name="customerConsentDataStrategy" ref="customerConsentDataStrategy"/>
        <property name="cartRestorationStrategy" ref="cartRestorationStrategy"/>
        <property name="forceDefaultTargetForUiExperienceLevel">
            <map key-type="de.hybris.platform.commerceservices.enums.UiExperienceLevel" value-type="java.lang.Boolean">
                <entry key="DESKTOP" value="false"/>
                <entry key="MOBILE" value="false"/>
            </map>
        </property>
        <property name="bruteForceAttackCounter" ref="bruteForceAttackCounter" />
        <property name="restrictedPages">
            <list>
                <value>/login</value>
            </list>
        </property>
        <property name="listRedirectUrlsForceDefaultTarget">
            <list>/example/redirect/todefault</list>
        </property>
    </bean>
    

    StorefrontAuthenticationSuccessHandler

    @Override
        public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
                                            final Authentication authentication) throws IOException, ServletException
        {
            //...
    
            //if redirected from some specific url, need to remove the cachedRequest to force use defaultTargetUrl
            final RequestCache requestCache = new HttpSessionRequestCache();
            final SavedRequest savedRequest = requestCache.getRequest(request, response);
    
            if (savedRequest != null)
            {
                for (final String redirectUrlForceDefaultTarget : getListRedirectUrlsForceDefaultTarget())
                {
                    if (savedRequest.getRedirectUrl().contains(redirectUrlForceDefaultTarget))
                    {
                        requestCache.removeRequest(request, response);
                        break;
                    }
                }
            }
    
          //...
        }
    

    Now reverse that logic by declaring new list (let's say listAllowedRedirectUrls ) or replacing listRedirectUrlsForceDefaultTarget with listAllowedRedirectUrls in the spring-security-config.xml and do the respective changes in the SuccessHandler. Like

    <property name="listAllowedRedirectUrls">
        <list>/p/</list>
        <list>/search</list>
    </property>
    

    StorefrontAuthenticationSuccessHandler

        if (savedRequest != null)
        {
            for (final String listAllowedRedirectUrl : getListAllowedRedirectUrls())
            {
                if ( ! savedRequest.getRedirectUrl().contains(listAllowedRedirectUrl))
                {
                    requestCache.removeRequest(request, response);
                    break;
                }
            }
        }
    

    You have to do the same changes for /login/checkout handler declaration (defaultLoginCheckoutAuthenticationSuccessHandler) as well.