Cookie-Based Token Retrieval Issue in Web Service Connector for Account Aggregation

:bangbang: Please be sure you’ve read the docs and API specs before asking for help. Also, please be sure you’ve searched the forum for your answer before you create a new topic.

Hello all,

I’m using a web service connector to integrate with an API. The API returns a token in the ‘Cookie’ response header, which I need to pass in subsequent API calls for account aggregation. To achieve this, I’ve created a BeforeConnector rule that:

  1. Calls the /token API to retrieve the token.
  2. Extracts the token from the ‘Cookie’ response header.
  3. Sets the token as a Bearer token in the actual request header.

Rule:

import java.util.*;
import org.json.*;
import connector.common.JsonUtil;
import sailpoint.connector.webservices.WebServicesClient;
import sailpoint.connector.webservices.EndPoint;

try {
    WebServicesClient client = new WebServicesClient();
    String url = "Login URI";
    Map args = new HashMap();
    args.put(WebServicesClient.ARG_URL, url);
    client.configure(args);
    Map header = new HashMap();
          
    header.put("Content-Type","application/json");
    
    List<String> allowedStatuses = new ArrayList();
    allowedStatuses.add("2**");
      
    Map payload = new HashMap();
    payload.put("jsonBody", "{\"clientId\":\"ID\",\"secret\":\"PWD\"}");
      
    String response = client.executePost(url, payload, header, allowedStatuses);
    // if response contains token it can be updated in the requestEndpoint header or body
    // the requestEndpoint will be used for execution of the particular operation configured
    log.info("BeforeOperation-Logger:TOKEN-API-RESPONSE-$$$$$$$$");
    log.info("BeforeOperation-Logger:response " + response);
    
    //Fetch the USER attribute from the cookies
    Map<String, String> cookies = client.getCookies();
    String userToken = null;
    for (Map.Entry<String, String> entry : cookies.entrySet()) {
        if (entry.getKey().startsWith("USER")) {
            String[] parts = entry.getValue().split("=");
            if (parts.length > 1) {
                userToken = parts[1];
                break;
            }
        }
    }
    log.info("$$$$$$-BeforeOperation-Logger:TOKEN-VALUE-$$$$$$$$");
    log.info(" token : " + userToken);    
    // Information can be fetched from requestEndpoint and updated in the header and body
    //Add to the requestEndPoint for usage in the Aggregation Rule
    if (userToken != null) {
        requestEndPoint.addHeader("X-XSRF-TOKEN", userToken);
    }

    log.error("BeforeOperation-Logger:requestEndPoint:" + requestEndPoint);
    
    String contextUrl = requestEndPoint.getContextUrl();
    log.error("BeforeOperation-Logger:contextUrl:" + contextUrl);
    
    String fullUrl =requestEndPoint.getFullUrl();
    log.error("BeforeOperation-Logger:fullUrl:" + fullUrl);
    
    Map body = requestEndPoint.getBody();
    log.error("BeforeOperation-Logger:body:" + body);

    Map header = requestEndPoint.getHeader();
    log.error("BeforeOperation-Logger:header:" + header);
    
    String jsonBody = (String) body.get("jsonBody");
    log.error("BeforeOperation-Logger:jsonBody:" + jsonBody);
    
    log.error("BeforeOperation-Logger:END");
    return requestEndPoint;

} catch (Exception e) {
    log.error("******Token Retreival exception*********")
    log.error(e.getMessage(), e);
}

When I call the Accounts aggregation API, I receive a response in the following format:

{
    "users": {
        "total-results": "243",
        "user": [
            {
               "name": "name",
               "email":"email"
             },
            {
               "name": "name-1",
               "email":"email-1"
             }
      ]
}

I’ve configured the connector with the following settings:

  • Root Path: $.users.user*
  • Response mapping:
    • name: $.name
    • email: $.email

I’ve also defined a schema with name and email fields.

When I enable CCG logs and run the aggregation, it completes successfully with 0 aggregated accounts. However, I don’t see any additional logs beyond the code being printed. Can someone help me identify what I might be missing?"

Hi @sita_ram ,

According to sample response you may change it to below format and try out.

Root Path: $.users.user
Response mapping:
name: name
email: email

Let me know if still you are facing issue.

Thanks

1 Like

@sita_ram :

  • Webservice before and after rule are cloud and logs are visible. You must ask your Profesionnal service contact if you want to see the rule logs execution

  • Your response root path must be : $.users.user

Thanks @ashutosh08 , @baoussounda for responding.

I changed the root path as suggested.

I see a 200-response code in ccg logs, that means the Before operation is calling the API and passing it to the GET call, but however, I still don’t get any accounts aggregated.

Could you please guide, if I am missing anything in the flow?

Hi @sita_ram,

Can you also put some after operation rule and see that the details are coming at this stage ?

If the details are present in the after operation, then there must be some other issue. Please let us know your observation from after operation.

Thanks

Hello @sita_ram

Can you try returning the requestEndpoint outside the try catch block?

Also, can you try this $.users.['user'] or $.users['user'] as Root Path
with Response mapping:

name: name
email: email

It seems client.getCookies() returns List of BasicClientCookie

  List cookies = client.getCookies();
    for (cookie: cookies) {
      if(cookie.getName().equals("JSESSIONID")){
        String sessId= cookie.getValue();
        application.setAttribute("sessionToken", sessId );
        break;
      }
    }

Hi @sita_ram

I believe in this situation, you should use the different approach where instead of using web service before operation rule you should use web service after operation rule.

The reason for this is that with web service before operation rule, we can only return the updated endpoint or an attribute that needs to be updated on source. Please refer to the below documentation for output variables

So, you should use the web service after operation rule because this will give you the flexibility to aggregate the accounts properly. In this rule, you can use the same logic as you have built and the only thing that will change is that you can return a map. The map should have a key “data” which should then have an List as below.

{
"data": [
{
"accountAttributeName1" : "accountAttributeValue1",
"accountAttributeName2" : "accountAttributeValue2",

}
]

}

where in your case , accountAttributeName1 will the account attribute name i.e name and accountAttributeName2 will have the value it should store which you need to pass it via variable in the rule.

This shall do the trick for you as you can then control the response mapping from the rule itself. Please use the below document for the reference

Please let me know if you have any queries in implementing it. Happy to assist.

Thank You.
Regards
Vikas

Hi @sita_ram,

According to sample response you may change it to below format rootpath and response mapping

Solution :1
RootPath: $.users.*

Response Mapping:
name: user[*].name
you can add more mapping if you have.

Solution : 2
RootPath: $.users.user[*]

Response Mapping:

name: name
email: email

Let me know if still you are facing issue.

Thank you.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.