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!!!!