By | 12 May 2014

Using SwitchUser in Integration Broker Subscriptions

There are times when writing integration broker subscription PeopleCode that you may want to change the user context. PeopleCode is always running under some user ID context. Therefore, certain actions in the system that the PeopleCode can take will be dictated by that user ID. This is especially true when invoking a component interface that has application level security or search records with data security. If your integration is setup as an “external node” type, the integration subscription PeopleCode will be running under the context of the default user ID on the node that processed the message.

In a recent project, I had to take the PS_TOKEN PeopleSoft Authentication cookie value and process some component interface code as the user identified by that PeopleSoft token and not the default users ID from the NODE. I will skip over the detail of how the external application got the PS_TOKEN value of the user to submit along with the request.

I thought I would share this stripped down example of how this is done for the communities use.

The OnRequest PeopleCode example does the following:

  • Reports the current user context in the response message before the switch
    • In this case, my environment was setup to process this message as user “GUEST
  • Look for a PS_TOKEN cookie value and perform “switchUser” using that token.
  • Reports the current user context after the switchUser.
    • In this test case the PS_TOKEN value represented the demo user “HAM_K0W004”

The code below relies on a related post about how to parse cookies in integration broker code: Parsing Cookies in Integration Broker Request Handler

import PS_PT:Integration:IRequestHandler;

class INBOUND_TESTER implements PS_PT:Integration:IRequestHandler
   method onRequest(&MSG As Message) Returns Message;
   method getCookieFromRequest(&MSG As Message, &cookieName As string) Returns string;

method onRequest
   /+ &MSG as Message +/
   /+ Returns Message +/
   /+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
   Local XmlDoc &xmlDocFromPython;
   Local XmlNode &requestRootNode;
   &xmlDocFromPython = &MSG.GetXmlDoc();
   &requestRootNode = &xmlDocFromPython.DocumentElement;
   /* Setup response xml body */
   Local Message &response;
   &response = CreateMessage(Operation.CHG_TEST, %IntBroker_Response);
   Local XmlDoc &xmlout;
   Local XmlNode &childNode;
   &xmlout = CreateXmlDoc("<?xml version='1.0'?><response/>");
   &childNode = &xmlout.DocumentElement.AddElement("user_before").AddText(%OperatorId);
   Local string &cValue;
   &cValue = %This.getCookieFromRequest(&MSG, "PS_TOKEN");
   If SwitchUser("", "", &cValue, "") Then
      &childNode = &xmlout.DocumentElement.AddElement("message").AddText("User Switched");
      /* SwitchUser Failed - Token probably invalid - Do some error handling */
      &childNode = &xmlout.DocumentElement.AddElement("message").AddText("Could not Switch to user identified by token");
   &childNode = &xmlout.DocumentElement.AddElement("user_after_switch").AddText(%OperatorId);
   Return &response;

method getCookieFromRequest
  /* ....snip ...   */
  /* See related KB post for this code */

The returned XML from the request looks like this:

<?xml version="1.0"?>
    <message>User Switched</message>

This is a rather useless example. The point here is that after a successful switch you can invoke component interfaces as the user you switched to and any audits or security happening in the underlying code will be as the user you switched to and not the “default node user.”

Additional Reading