Skip to Content

Some Web applications are securing their applications with the x-csrf-token. This requires you to call the service to get a token before you do the modification of the objects. This is at the moment not support the REST adapter in SAP PI/PO. But it could probably be added later.

The scenario looks like the following. In our message mapping, we will perform a lookup call to a Rest adapter to get the x-csrf-token. Then we have an adapter module that we use to call the service with.

 

You can see the video where I’m describing how to setup the system.

Here is the UDF method that calls to get the token.

	@LibraryMethod(title="lookupToken", description="get token from service", category="RestLookup", type=ExecutionType.SINGLE_VALUE) 
	public String lookupToken (
		 Container container)  throws StreamTransformationException{
		AbstractTrace trace = container.getTrace();
	     Map<String, Object> all = container.getInputHeader().getAll();
		
	     Channel restChannel = LookupService.getChannel("B2B","ReceiverRestToken");
			SystemAccessor restAccessor = LookupService.getSystemAccessor(restChannel);
			trace.addInfo("got channel ");
			  XmlPayload payload = LookupService.getXmlPayload( new ByteArrayInputStream("<root/>".getBytes()));
			Payload response = restAccessor.call(payload);
			trace.addInfo("got response");
			String payloadContent = "";
			try {
				payloadContent = readbytes(response.getContent());
				
				trace.addInfo(payloadContent);
			} catch (IOException e1) {
				trace.addWarning("IO Exception " +e1.getMessage());
			}
			
			
			try{
	     
	     DynamicConfiguration config = (DynamicConfiguration)all.get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
		   
		
		    //Define key to write in the Dynamic Configuration
		    DynamicConfigurationKey key1 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST","token");
		    config.put(key1,payloadContent );
			}catch(Exception e){ 
				trace.addWarning("Unable to set dynamic configuration" );
			}
		    
		return "";
	}

	private String readbytes(InputStream inputStream) throws IOException{
	ByteArrayOutputStream result = new ByteArrayOutputStream();
	byte[] buffer = new byte[1024];
	int length;
	while ((length = inputStream.read(buffer)) != -1) {
	    result.write(buffer, 0, length);
	}
	// StandardCharsets.UTF_8.name() > JDK 7
	return result.toString("UTF-8");
	}

Then we have the adapter module that you need to include a software component and deploy together with your other modules.

public class SetTokenModule implements Module, SessionBean {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4916672969815060014L;
	private static final Location LOC = Location.getLocation(SetTokenModule.class);
	private AuditAccess audit;

	@Override
	public ModuleData process(ModuleContext context, ModuleData inputmoduleData) throws ModuleException {
		try {
		Message msg = (Message) inputmoduleData.getPrincipalData();
		 MessageKey key = msg.getMessageKey();
		
			audit = PublicAPIAccessFactory.getPublicAPIAccess()
					.getAuditAccess();
				audit.addAuditLogEntry(key, AuditLogStatus.SUCCESS,
				"TokenModule: Module called");
				MessagePropertyKey tokenKey = new MessagePropertyKey("x-csrf-token","http://sap.com/xi/XI/System/REST");
				
				String token = msg.getMessageProperty(tokenKey);
				audit.addAuditLogEntry(key, AuditLogStatus.SUCCESS,
						"TokenModule: Tokenvalue "+token);
				TextPayload tokenPayload = msg.createTextPayload();
				tokenPayload.setText(token);
				msg.setMainPayload(tokenPayload);
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return inputmoduleData;
	}
}

The post channel configuration should look like the following.

And to get the token to the adapter you need to add the header properties like the following.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. Piotr Radzki

    Hi Daniel,

    Nice, I currently do the same (manually) from Postman while testing S4 HANA Cloud API directly, without using CPI. Some of them, especially POST (Create CRUD opeations) require x-csrf-token for communication, not only basic authentication. It’s nice that you share the code Daniel. Thanks!

    BR,

    Piotr

    (1) 

Leave a Reply