How best to use On Behalf Of?

I was pondering how best to support On Behalf Of (OBO) in my iParts in addition to the existing support for Logged In ID and Selected ID, when I realized that ASI may have already solved part of this puzzle.

Are there any guidelines or patterns for how these three entities should be used?  My initial perception is that OBO substitutes partially for Logged In ID, but things can get really fuzzy when you start playing with combinations.

Here are some example scenarios I'm concerned about.  In each case, L is the logged-in ID, S is the Selected ID (falls back to L when blank) and B is OBO (falls back to L when blank).

  1. If B has more rights than L, should the user have more rights than normal or the same?  (Navigation items, queries and other documents, fields they can see/edit)
  2. How about when B has less rights than L?  Should the capabilities be reduced so the user is seeing exactly what B would see?
  3. If someone logs in but has not searched for a record (S = L), but has entered OBO (B != L) and goes to an "edit my profile" page, should they edit the B or the L record?
  4. User logs in, finds a record S, and engages OBO.  Now they click "Change" and go back to "their own" record.  Would that be L or B?
  5. When OBO is in effect, should change log entries and LastUpdatedBy fields be attributed to B or L?
  6. If L is a CompanyAdministrator and B is not, can the user do CompanyAdministrator type things on behalf of B?
  7. If L and B have different member type edit rules, which rules apply?
  8. If L and B have different access keywords or roles, which rules apply?
  9. If L is registering B for an event, should they see the only the choices B can see ("true to B's view") or should their permissions allow different choices ("L can perform an override", but also "L can't use OBO to get around a security rule")?
  10. Does IQA use L or B for @Me, or is there a way to specify which is intended?
  11. If the user engages OBO, and by being B is able to see different search results to get an S they shouldn't normally get, what happens (and what should happen) when OBO is disengaged?

I think that's probably enough.

For most of these, I can see arguments for either answer.  I also recognize that some situations will call for exceptions.  I'm not here to design the feature, nor bury it, but to understand it.  I'm really hoping ASI has come up with a clear definition of how it is meant to work that clarifies the scenarios above and many others like them.

Any guidance?

-- Bruce Wilson
Director, Technology Solutions
McGladrey LLP

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

A brief discussion of On Behalf Of

Let me begin by attempting to clarify what On Behalf Of really means.

The only users who should ever need to directly use the OBO control that we see in the latest deployments of the Member website are those users that we might call Customer Service Representatives (CSR).

These would generally be staff-type users with a role that involves answering incoming calls from members and performing some type of commerce transactions on their behalf. Perhaps the better way to think of these users would be those who might traditionally have lived in the Service Central area of iMIS Desktop. Of course, the lines always blur whenever you have users who are permitted to enter commerce transactions in a given feature area (e.g., Register people for events or enter orders).

For the most part, staff-type users should find members by performing a search (currently, by using the Directory find) and selecting the person or organization from the search results. We are working on a new device that will allow the majority of such users to simply click a link or button while viewing a person or organization to begin a new commerce transaction (event registration, order, etc.) on behalf of the currently selected record (provided that the logged-in user has permissions to do so). This link/button will - without the logged-in user even needing to know about the OBO control - set the OBO target as the currently selected record.

What is most important to recognize is that all non-commerce type of interactions with a person or organization record can be performed without ever using On Behalf Of.

Now, to address some of the scenarios you presented...

1-3:  Permissions are always determined based on the logged-in user (L). Selecting a person (S) only identifies that person as the currently active record for the purpose of refreshing certain data displayed on the profile pages (account pages).

For users with some level of access to OBO, setting the OBO target (B) only affects the relevant properties of an SOA Cart-ComboOrder (i.e., SoldToCustomerParty, BillToCustomerParty).

4:  If I'm understanding this scenario correctly, you are referring to choosing oneself as the OBO target. In this case, my logical answer would be to not do that - just clear the OBO target. However, we do not currently prevent it from happening, so if a user with access to OBO does do this, then the Logged-in user (L) and the OBO target (B) would be the same. Clicking on the logged-in user's (L) name in the utility nav will always display the logged-in user's profile/account page. Clicking on the OBO target's (B) name in the OBO control will always display the OBO target's (B) profile/account page.

One point that this reminds me of is that having an OBO target (B) set does not override any use of a selected ID (S). In fact, there are several legitimate scenarios where a CSR might be working on behalf of one person and still need to go look at another person's record. What should be noted about this scenario is that the selected ID is transient (i.e., it only exists when passed in a URL parameter).

5, 7-8:  All actions performed are always attributed to the logged-in user (L). When working on behalf of someone, the logged-in user (L) is the one who is performing actions and is the user whose permissions determine what actions can be performed. Note, however, that not all of the legacy security rules are currently enforced through SOA (e.g., Access Keywords).

6:  I am pretty sure that this one is not a valid scenario since only Full Users should ever be permitted to enter transactions on behalf of others. It is worth noting that the "Register someone else" feature is not using OBO and, in fact, only affect the SOA Cart-ComboOrder "Ship To Address" (OrderLine.DeliveryId) for the resulting registration. Nevertheless, a Company Administrator should be able to perform "Company Administrator type things."

9:  The same permissions rules apply as from 1-3, 5, 7, and 8. So the logged-in user (L) will see what she is permitted to see. But even if she is able to see a program item for which the OBO target (B) is not eligible, she would not be able to add that item to the registration

10:  The best explanation of this is directly from the current documentation - http://docs.imis.com/15.2/#!addingdynamicfilters.htm. One caveat that I want to interject here is that references to user impersonation are specific to the iMISPublic view and should be ignored for iParts-based websites. You should never develop your iParts-based website with the expectation that this legacy user impersonation will be available since we will remove it from the product at some future time

11: The same permissions rules apply as from 1-3, 5, 7, and 8. So the logged-in user (L) will see what she is permitted to see - not what the OBO target (B) is permitted to see.

OBO == Selected?

Hi, Jeffrey,

Thanks for this detailed explanation. I should have replied long ago, as I have come to this page and reread it several times.

I realized that nowhere in the above did I ask an important question: how to request "B" (the current on-behalf-of) contact from iMIS. There are quite a few examples in old and new code for retrieving the logged in ID (L) and selected ID (S), but I don't think the B portion has ever been explicitly defined.

The docs link you gave (http://docs.imis.com/15.2/#!addingdynamicfilters.htm) suggests that B and S are the same thing, at least for IQA filters. Are they exactly the same thing in all places, or is there a different way to determine the current OBO?

--
Bruce Wilson
Director, Technology Solutions
McGladrey LLP

S can either be L or B

S can either be L or B. Commerce iParts/code call Asi.Security.Utility.SecurityHelper.GetSelectedImisIdForCart() to determine whose information to use (that method will not look in the Querystring for an ID of a user). Non-commerce iParts/code that wish to honor OBO call Asi.Security.Utility.SecurityHelper.GetSelectedImisId(). Currently, there is no method or property that will either return B, or null or empty if B has not been set.

OK, trying to parse this...

So, I'm trying to combine this information with what Jeffrey shared before and come up with a model in my head I can work with.

It appears that GetSelectedImisId* methods all refer to the OBO if set. Therefore, when asking for S, I will get B (if set) or L (if not set) or another indicator if not logged in at all (could be blank or GUEST depending on the method I call and the params I pass). As far as I can see, the only other meaning of "selected ID" is when the ID is passed on the URL. The old definition of selected ID (a sticky value that the application remembers until you change it) is now called OBO.

It also appears that the only difference between GetSelectedImisId and GetSelectedImisIdForCart is that ...ForCart will ignore the URL param. I'm not exactly sure why that is a cart-related thing, but I'll take that as read until I need to do something with the cart.

As indicated above, feature permissions are always based on who is logged in. I would hope that Item/Entity permissions can be affected by the OBO record, so that (for example) if a person is not allowed to register for an event (no price rules exist), that the logged in user may be blocked from registering them inappropriately. (That's a separate discussion, I'm sure.)

So in summary:

- Logged in is always logged in. Nothing overrides it.
- On Behalf Of is the new name for a long-lasting selected record. iMIS will remember this ID until it is explicitly changed.
- A URL param is now used for transient selected records. It supersedes OBO without causing iMIS to forget the OBO ID. When it is dropped from the URL, GetSelected goes back to the OBO ID (if any).

So for my development purposes, it sounds like I just keep using GetSelectedImisId, and I need to decide whether it is appropriate for the URL param to override the OBO value on a case-by-case basis.

--
Bruce Wilson
Director, Technology Solutions
McGladrey LLP

Sounds like you've mostly got the concept right

... and thank you for helping to put some clarity on what is not an easy thing to grasp. I hope many others will find value in this discussion.

To reiterate what I began with in my earlier reply, OBO is specifically intended for use as a way for a privileged user to perform commerce type actions on behalf of another Party (any iPart that performs this type of action - not just the cart - should use GetSelectedImisIdForCart). Everybody else should always use the Directory find feature to lookup people and organizations (all iParts that need to respond to a selected Party should use GetSelectedImisId). The latter is one of the ways that an ID can get set in the URL.

Following this approach, you should be able to design most of your iParts to use the appropriate method based on the functionality being delivered. You should also consider whether or not any element of your iPart will navigate the user to another page where the PartyID from the URL should be passed along.

For example, in some of the recent sprints, we've seen addition of linking functionality for the Primary Organization name in the MiniProfile and the ability to navigate to a different Party by clicking a node in the GroupListEditor. In each of these cases, the target URL passes the ID. Of course, your iPart might also need to pass the same ID as it received in order to display other information for the same Party.

Finally, if I am interpreting your reference above correctly, you were suggesting that the legacy concept of Broadcast ID is now embodied in OBO. I would discourage that comparison since (as I've reiterated above) OBO is not designed to be used in quite the same way.

Broadcast?

I haven't heard the term Broadcast ID before, so I can't tell whether I'm using it.

My original code (derived from ASI-provided examples) determined Selected ID by decrypting request.Cookies["UserID"]. More recently, I switched to using SecurityHelper.

If "ForCart" is not just for the cart, then I would suggest that it is named improperly. How about adding/exposing ignoreParamValue, much like includeAnonymousUser, as a parameter to GetSelectedImisId? This makes it easier for developers outside of ASI to see they have a choice, and to make the right choice.

It's good you mentioned this intended behavior. Most of my iParts assume that the "sticky" selected ID is available and reliable. What you're saying makes it sound like I can't expect it to be available for non-privileged (which in most cases means non-staff). Not sure if I like this, but better to know it so I can figure out what to do about it.

--
Bruce Wilson
Director, Technology Solutions
McGladrey LLP

I think Jeffrey...

I think Jeffrey was referring to Desktop when he mentioned the Broadcast ID.

You are correct that the SecurityHelper has replaced the functionality that was previously stored in cookies. That was the old "impersonation" model that was built into the public views. The security helper still respects impersonation if it is in use, but when it is removed one day the security helper should make that transition very smooth/invisible.

ForCart is probably really ForCommerce. Commerce/Cart iParts were the only use case we have in out-of-the-box iMIS for not respecting the ID in the URL so that's probably why we named it this way. It's funny you mention the boolean parameter because underneath that is actually how it's implemented. Maybe we should expose this as a public method and retire GetSelectedImisIdForCart one day...

And actually, we just went through some clean up on the SecurityHelper that you should see in the next release of iMIS. The only major change is that GetSelectedImisId will never return "GUEST" anymore. This was a bug in the initial implementation as it is not actually a proper iMIS ID. The other changes you will see are better API/intellisense documentation. This should make it a little more clear what results you can expect back from each of the methods.

Your idea of letting non-staff users be able to have a "sticky" selected ID is an interesting one. If you have a good use case for this I'd suggest talking to the iMIS product owners.

Cheers,
Courtney Robertson

Use case, briefly

I know you said owners, but I'll put an idea here too. The main defense I can make of the idea is that the line between staff and non-staff is getting more and more blurry. Chapter leaders often need staff-like powers, and this is starting to include committee chairs and other volunteers. CompanyAdministrator is typically used within a company but easily modified in the field to use any set of "is someone related to me" rules we choose (and we often do).

It's not a random coincidence that I mentioned the boolean parameter. Isn't reflection wonderful? :)

As a programmer, I like having direct control of the available options instead of using differently named methods which happen to match my intent. On the other hand, I appreciate and respect that it's often better for me to deal with an abstraction and not get too married to the implementation so the implementation can be changed. (Classic implementation hiding and all that.) I think it would be useful to expose this particular parameter, then through naming and intellisense, give guidance on when it is meant to be used.

Good to know about GUEST. As you might have inferred from this thread, I'm looking at how to incorporate the information from SecurityHelper into the library we use in all our projects. I'll step carefully around that pothole and try to pretend it isn't there.

--
Bruce Wilson
Director, Technology Solutions
McGladrey LLP

Are cookies dead, yet?

You mention that someday the cookies will no longer work. I'm running into a new problem with Selected ID which may be related to this.

One of my iParts uses some old IQAViewer sample code to do something magical and special with the links in the query results. When running on 15.2.5, the selected ID isn't always handled right. Here's a snippet:

	// OK Now Fun Part - We have URL - But we can not go right now - we have to set Current iMIS ID first and then GO
	// This one works VIA submit, but eventually we will fix it!
	// Apporach will be - Use PAGE METHOD
	link = new LinkButton {EnableViewState = true, Text = item[col.ColumnName].Text};

	// Call special Method to Generate COOKIES info
	string cookieName;
	string cookieValue;
	string cookieDomain;
	string cookiePath;
	DateTime cookieExpire;

	IMIS.GetSelectedIDFromCookie(userValue, Request, out cookieValue, out cookieDomain, out cookiePath, out cookieName, out cookieExpire);

	link.OnClientClick = "NavigateViaHelper('" + url + "','" + userValue + "','" + (newWindow ? "1" : "0") + "','" + cookieName + "','" + cookieValue + "','" + cookieDomain + "','" + cookiePath + "'); return cancelEvent();";

	link.ToolTip = "Click on the text to navigate. Link will open in " + (newWindow ? "a new" : "this") + " window.";
	item[col.ColumnName].Controls.Add(link);

IMIS.GetSelectedIDFromCookie is part of my library, also originally from an iParts example. It looks like this:

	public static void GetSelectedIDFromCookie(string iMISID, HttpRequest request, out string cookieValue, out string cookieDomain, out string cookiePath, out string cookieName, out DateTime cookieExpires)
	{
		Secure tool = new Secure();
		string id = tool.Encrypt(iMISID);

		cookieValue = id;
		cookieName = "UserID";

		HttpCookie httpCookie = request.Cookies["Login"];
		if (httpCookie != null)
		{
			cookieDomain = httpCookie.Domain;
			cookiePath = httpCookie.Path;
			cookieExpires = httpCookie.Expires;
		}
		else
		{
			cookieDomain = null;
			cookiePath = null;
			cookieExpires = new DateTime();
		}
	}

Finally, NavigateViaHelper (Javascript) looks like this:

	function NavigateViaHelper(url, IDValue, windowstatus, CookieName, CookieValue, CookieDomain, CookiePath) {
		//// Now Check for mode then set cookie and navigate
		// We Only Set Path and Value
		document.cookie = CookieName + '=' + CookieValue + ';' + ' path=' + CookiePath + ';';
		if (windowstatus == "1")
			window.open(url);
		else
			window.location = url;
	}

(Lots of unused variables there, but I will disclaim any fault for code I didn't write.)

So, if the cookie is no longer being used for selected ID, I will have to modify this area of code which I don't fully understand to do things another way. If the cookie *is* still used, then maybe I'm looking at some changes in the stock Javascript which are interfering with the existing code?

Any suggestions appreciated.
--
Bruce Wilson
Director, Technology Solutions
McGladrey LLP

SecurityHelper.GetSelectedImisId

Hi Bruce,
Did you get any more feedback from ASI on this. We have a similar problem having just upgraded to 15.2.15 where Request.Cookie["iMISID"] no longer works.
substituting SecurityHelper.GetSelectedImisId returns the currently logged in user not the selected user which I suspect points back to your discussion above.
Any comment greatly appreciated. We are trying to do this in Desktop iMIS.

Thanks
Keith Robertson
MAST-ICT Ltd
UK

Not yet

I haven't heard back yet. What you see above is about all I know on the subject. Sorry.
--
Bruce Wilson
Director, Technology Solutions
McGladrey LLP