WebserviceBeforeOperation rule body syntax

Hello developper community,

I am trying to make an authentication request using a connector rule but I get an error when creating my json body. I tried to use the example in the community documentation but I still get an error when using :

payload.put("jsonBody","{"concurrentSession":"false","Username":"username","Password","password"}");

Do you have some suggestions ?
Thanks.

Here is my code

  import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.HashMap;

    import sailpoint.object.Application;
    import sailpoint.tools.Util;
    import sailpoint.tools.GeneralException;
    import sailpoint.connector.webservices.EndPoint;
    import sailpoint.connector.webservices.WebServicesClient;
    import sailpoint.object.ProvisioningPlan;

	import connector.common.Util;

	
    log.error("[WebserviceBeforeOperationRule-Get Authorization token] Executing");

    // get login credential
  	String username =  application.getAttributeValue("username");
  	String password =  application.getAttributeValue("password");

    // get the base url and build the token URL
  	String contextUrl = application.getAttributeValue("genericWebServiceBaseUrl");
	String tokenPath = "/Passwordvault/Api/Auth/CyberArk/Logon";
  	String tokenUrl = contextUrl + tokenPath;


  	String responseBody = null;

    log.error("[WebserviceBeforeOperationRule-Get Authorization token] authentication loginUrl: " + tokenUrl);

  	// Create the header
  	Map header = new HashMap();
  	List<String> allowedStatuses = new ArrayList();
    allowedStatuses.add("2**");
    allowedStatuses.add("3**");

	log.error("[WebserviceBeforeOperationRule-Get Authorization token] authentication loginUrl: ") ;
	 
  	try {
 	  	log.error("[WebserviceBeforeOperationRule-Get Authorization token] Requesting the token calculation endpoint ");

  		// Set up args and WebServicesClient
  		Map args = new HashMap();
  		WebServicesClient client = new WebServicesClient();

  		args.put(WebServicesClient.ARG_URL, tokenUrl);
  		client.configure(args);

	  	header.put("Content-Type","application/json");

		// configuring the payload of the post
		Map payload = new HashMap();
		log.error("[Webservice " + username + password);
		payload.put("jsonBody","{"concurrentSession":"false","Username":"username","Password","password"}");
		//payload.put("concurrentSession", "false");
		//payload.put("Username", username);
		//payload.put("Password", password);
		
    
		
        try {
        	log.error("[WebserviceBeforeOperationRule-Get authorization token] POST with header: " + header + " and payload: " + payload);
        	responseBody = client.executePost(tokenUrl, payload, header, allowedStatuses);
      } catch (Exception e) {
          log.error("[WebserviceBeforeOperationRule-Get Authorization token] Exception with message: " + e.getMessage());
        }
  		// Log the post response of token url
  		log.error("[WebserviceBeforeOperationRule-Get Authorization token] POST " + tokenUrl + " - responseHeader: " + responseHeader + " - responseBody: " + responseBody);
  		authToken=responseBody.toString();
		header.put("Authorization", authToken);

  	} catch (Exception e) {
        log.error("[WebserviceBeforeOperationRule-Get Authorization token] Exception with message: " + e.getMessage());
    }

  	// Set requestEndPoint with new header
  	log.error("[WebserviceBeforeOperationRule-Get Authorization token] the header is set to: " + header);
  	requestEndPoint.setHeader(header);

  	// finally, return the requestEndPoint
  	log.error("[WebserviceBeforeOperationRule-Get CSRFToken] Exiting ");
    return requestEndPoint;

Hi @JosquinClv ,

What error are you getting?

Assuming the Error is with setting up the payload. You can try this code:

import connector.common.JsonUtil;

Map payload = new HashMap();
Map jsonMap = new HashMap();

jsonMap.put("concurrentSession", "false");
jsonMap.put("Username", username);
jsonMap.put("Password", password);
payload.put("jsonBody", JsonUtil.render(jsonMap));

Hi @colin_mckibben

I am facing an : Exception occurred in Test Connection. Error: Error executing before operation rule for endpoint ‘Test connection’: BeanShell script error: bsh.ParseException: Parse error at line 57, column 28. Encountered: ( BSF info: BeforeOperationRule at line: 0 column: columnNo

with the line 57 where I am setting up my payload

Hello @atarodia thanks for the answer,

When using your code I am facing an error 400 bad request.
Here is what the payload looks like in that case

Looks like @atarodia’s suggestion got you a little further. You’re no longer getting a parsing error, but the API endpoint you are hitting is complaining about a bad payload. What does a valid request body for that endpoint look like? How does a valid payload differ from the one you are trying to send?

1 Like

The payload needs to be on this format :{ "username":"name", "concurrentSession":"false", "password": "pswd" }

I actually got a pretty close result using this code :
payload.put("concurrentSession", "false"); payload.put("username", username); payload.put("password", password);
which gave me this payload but I think it is missing the quotation mark

I think I found the API you are using. Is this the one? CyberArk, LDAP, RADIUS, Windows

If so, then I think the issue has to do with the concurrentSession property. The doc says it needs to be a boolean, but you are assigning a string to it. Try this code when setting the property:

jsonMap.put("concurrentSession", false);

Thank you @colin_mckibben for finding the API. @JosquinClv You can use this payload:

Map payload = new HashMap();
payload.put("jsonBody","{"username":"$application.username$","password":"$application.password$","concurrentSession":false}");

Thanks @colin_mckibben and @atarodia it was the right API

I changed my rule using

Map payload = new HashMap();
payload.put("jsonBody","{"username":"$application.username$","password":"$application.password$","concurrentSession":false}");

And I got the same parsing error : Exception occurred in Test Connection. Error: Error executing before operation rule for endpoint ‘Test connection’: BeanShell script error: bsh.ParseException: Parse error at line 70, column 28. Encountered: ( BSF info: BeforeOperationRule at line: 0 column: columnNo

I tried the other way using

jsonMap.put("concurrentSession", false); jsonMap.put("Username", username); jsonMap.put("Password", password); payload.put("jsonBody", JsonUtil.render(jsonMap))

and I am facing an error 403. ( I checked my credentials and I do use the right ones)

I suggest using the second approach which gives you the 403 error. One thing to note, you don’t need to explicitly set the concurrentSession to false. By default, it will be false, per the API doc. Better to just leave it out.

Are you able to call this API in Postman? I’m curious if you can successfully generate a token manually before trying to call it in this rule.

Yes I ve been able to call this API with Postman and it is successfull. I am using this body for the call
{ "username":"name", "concurrentSession":"false", "password": "pswd" }

Can you trigger a 403 response when using postman? What did you have to change to get the 403? Is it a bad username or password? This will help us narrow down the cause of the 403 in the rule.

To get a 403 on Postman I had to use a bad username or password. The other changes got me a 404.
Also I am checking the credentials in the log a step ahead and they are in good form.

The credentials might look good before you send the request, but I wonder if the request is encoding them incorrectly. Are you able to log the actual request being sent?

Also, im not sure if this will fix it, but you are capitalizing Username and Password in your jsonBody. Make those lower case like you did in postman.

I am not able to log the actual request with

log.error("[Webservice] " + client.executePost(tokenUrl, payload, header, allowedStatuses) );
		log.error("[Webservice] " + toString(client.executePost(tokenUrl, payload, header, allowedStatuses)) );

But I got the header and body before the request

I asked if we had all the permission to access the application. In case some changes were made.

If the payload looks correct, then I agree, check with CyberArk to see if permissions have changed. Clearly, the rule is able to reach the API, but getting a 403. This usually means the server has received the request but can’t authorize it.