How to submit a form to Hybris from external application

Gate crash is embarrassing, back door entry is risky. Great is to be welcomed by a friend inside the party, when you are not invited.

Recently, i came to a situation, where i wanted to submit a form to hybris from a application. I thought it would be easy, and all i need is to do a post to a URL.

Booom. It came out with a flat Bad or missing csrf value error.

Once i thought, perhaps i am trying to breach the hybris security. Since there is a contract between client (browser) and the server (hybris) to exchange information. To keep this information just between them, a shared private token is used. This token, known as csrf token, is bound to a session.

@sumitg88 talked about it one of his blog.

Bypassing a request from security layer is one thing. What i wanted was to go through the security layer, and still be able to submit a form, from outside the spring context of Hybris storefront.

I created an API in storefront, which can pass a csrf-token for the current session. The current session can be opened by application, by hitting the home page, may be in an iframe, or through a java program in backend.

Hybris forcefully adds a csrf token inside a hidden field, in every spring mvc form. You can see this happening by going to html source of a page with form. This token is actually validated against the session token to allow a request to pass to the services.

hiddenFields.put(CSRFTokenManager.CSRF_PARAM_NAME, CSRFTokenManager.getTokenForSession(request.getSession()));

In Html forms you can see:

      <input type="hidden" name="CSRFToken" value="0b4eefff-1a05-4bdb-843a-fa9598633dab">

Our API could give the same csrf token, which we can pass through our form in external application. This way, Hybris will take this request as a valid one, and we can submit the form.

The API could look like below:

      public static String getTokenForSession(final HttpSession session)
	{

		// cannot allow more than one token on a session - in the case of two requests trying to
		// init the token concurrently
		Enumeration<String> enumeration=session.getAttributeNames();
		String csrfTokenAttr=null;
		String token=null;
		while(enumeration.hasMoreElements())
		{
			String attrName=enumeration.nextElement();

			if (attrName.contains("CSRFTokenManager.tokenval"))
			{ 
				csrfTokenAttr=attrName;
			}
		}
		synchronized (session)
		{
			token = (String) session.getAttribute(csrfTokenAttr);
			if (null == token)
			{
				token = UUID.randomUUID().toString();
				session.setAttribute(csrfTokenAttr, token);
			}
		}
		return token;
	}

Once you have a valid token, from one of the session, you can submit any form smoothly.

Enjoy!!!!

Load balancer Redirection issue

In clustered environment it’s very common to terminate SSL at load balancer layer and pass non secure requests to Hybris applications servers.

This brings in some complexities if configuration is not correct.

As hybris servers get http request so in case redirection is required they redirect to same non secure protocol which is then recreated into secure request by rules configured at load balancer layer.

To avoid this unnecessary redirection and other potential session issues you have to configure all application servers to redirect to specific port and name.

Add following attributes to <Connector port=”${tomcat.http.port}” in server.xml files of all servers:

proxyPort=”443″ proxyName=”${proxyName}

proxyName – URL of application e.g. google.com

Setting up ASM (assisted service module ) and facing : “Error creating bean with name ‘getAssistedservicestorefrontBeforeViewHandler’”

Are you facing this exception while setting up Assisted Service Module:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘getAssistedservicestorefrontBeforeViewHandler’: Post-processing of FactoryBean’s singleton object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy160]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy160

Solution:

Disable Autoproxy – remove entry “<aop:aspectj-autoproxy />” from assistedservicestorefront-web-spring.xml and restart server.. boom!!

 

Error submitting a form due to Cross Site Request Forgery (CSRF)

Recently I faced a problem when I was trying to simply create a Form and a Controller to accept the values submitted from the form. I was using Hybris 5.7 version.

When I entered and submitted some values in the form (or even submitting an empty form) I was continuously getting the following error in the browser and the program control was not reaching my controller:

http status 403 bad or missing CSRF value

After doing lot of googling I found that the above error was coming while sending a “POST” request from any Form and was due to the interceptor “csrfHandlerInterceptor” configured in spring-mvc-config.xml of my storefront. This interceptor is configured to prevent Cross Site Request Forgery (CSRF).

Now to fix this error, there are 2 options:

  1. either the CSRF token in the request matches the session CSRF token to ascertain the validity of incoming posts requests.
  2. or the requested URL is a trusted path and is allowed to go through without CSRF token validation

For the 1st point you need to configure and send a valid CSRF token in your request. You can find information regarding this at: http://docs.spring.io/spring-security/site/docs/3.2.0.CI-SNAPSHOT/reference/html/csrf.html

For the 2nd point you can add your URL entry to “csrfAllowedUrlPatternsList” in your storefront’s spring-mvc-config.xml file as shown below:

<util:list id=”csrfAllowedUrlPatternsList” value-type=”java.lang.String”>
             <value>/upload/createmedia</value>
</util:list>

Please note that for additional details there is a good article on CSRF in Hybris Wiki at the following URL:

https://wiki.hybris.com/display/accdoc/Spring+Security