AppPrincipal and IiMISUser

I've been spending more time than I wanted, trying to figure out how to use AsiMembership provider and how it's meant to work alongside RoleProvider and Asi.iBO.dll in general. Frankly, I'm a fair amount unhappy that this kind of stuff is not documented - it seems crazy that I'm having to dig around to find out how things are supposed to integrate together.

It seems that in certain areas the custom Membership provider (AsiMembershipProvider) is not going to work well with iBO.Net.

Here are my observations thus far:

  1. Making a call to the AsiMembershipProvider.ValidateUser creates an AppPrinicpal object and assigns that to HttpContext.Current.User and Thread.CurrentPrinipal
  2. This AppPrincipal object gets loaded with roles from a call to a stored proc in IMIS database. Also if an app has enabled RoleProvider, it will also ask the RoleProvider for roles and merge these with the roles returned from IMIS
  3. Hell AppPrincipal looks an important object to have around. There are plenty of places in iBO.Net that expect an instance to be assigned to Thread.CurrentPrincipal. So I was VERY surprised to see that CContactUser.LoginByWebLogin does not create one of these objects and assign them to Thread.CurrentPrinical.
  4. Further digging around, I see that if a call is made to CStaffUser.LoginByUserId, the AppPrincipal object will get created and assigned to Thread.CurrentPrinicpal.
  5.  An app that uses the AsiMembershipProvider still must call a CContactUser.LoginByXxx method to get an all important IiMISUser object back - the API is quite confusing when considered in conjunction with the fact that AsiMembershipProvider has already "logged in" and setup an AppPrincipal object

I need someone from Asi to clarify a few things:

  1. Logging in using the CContactUser and CStaffUser - why does one create an AppPrincipal and the other does not?
  2. Because CContactUser.LoginByWebLogin does not create and assign to Thread.CurrentPrinicpal an AppPrincipal, surely this will eventually result in a null reference exception at some point when calling classes inside of iBO.Net or related Asi assemblies?
  3. When does an app need to call CStaffUser.LoginByXxx, instead of CContactUser.LoginByXxx? I assume when the visitor of the website represents a Staff user? In which case, a call to CStaffUser.LoginByXxx is going to duplicate and also stomp over the AppPrincipal created by the AsiMemberProvider. Very inefficient and very annoying - is there any way to avoid this? (yes I know about the extra parameter - setAppPrincipal - calling code can supply this, but that does not stop all the redundant database calls being made).
  4. I have just read there is an AsiRoleProvider - which Asi assembly is this in?

Thanks

Christian Crowhurst

Comment viewing options

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

Christian: Unfortunately a

Christian:

Unfortunately a lot of the overlap here is due to parallel development. At the time iBO.NET was being developed, it was intended to be a version-neutral API (that is, able to run equally against everything from 10.6 to 15.x and into the future). The downside to this approach, and one of the major reasons iBO.NET is now supported only with the version it ships with, is that it greatly complicates development, particularly the attempt to support 10.x. This is because 10.x did not require the .NET install or database tables, so when it came time to implement logins, the solution ended up not being as clean as it could have been. If I could go back and change it I would have iBO.NET use AppPrincipal rather than IiMISUsers.

iBO.NET only uses AppPrincipals when it calls into the other iMIS.NET APIs, which are all dependent on that authentication method. These should be pretty few and far between, honestly; generally using an IiMISUser should be enough. If you find a situation where this isn't true, you might either post reproduction code in these forums, and/or file an SMR with tech support so that eventually the need to manually do both is eliminated.

As far as I know there is no shipping AsiRoleProvider. There should be one shipped in the next major release of iMIS, but I don't have any timeline on when that will be. When it does ship it will be in the Asi.Providers assembly/namespace.

Eric Means
System Architect, ASI

Downside of using IiMISUser

The major problem I see with IiMISUser: it has limited to no support for loading roles - CStaffUser is the only class that even loads roles, and these are limited to those stored in UserToken table. This was the main reason I started looking at the AsiMembershipProvider.

So how about I do the following:

  1. Use AsiMembershipProvider to create and assign to Thread.CurrentPrincipal an AppPrincipal object
  2. Use Asi.Web.Security.EstablishAppContext to ensure that an existing AppPrinicipal stored in session state, gets assigned to Thread.CurrentPrincipal and HttpContext.Current.User on subsequent post backs
  3. Implement my own RoleProvider to return a set of custom roles. In this way AsiMembershipProvider will merge my roles into the AppPrincipal being created 
  4. Only use CContactUser.LoginByXxx to get a reference to an IiMISUser, ie don't use CStaffUser.LoginByXxx. I see that if I need a CStaffUser instance then CContactUser.StaffUser will give me the necessary reference (so long as CContactUser is a staff user)

Can you see any flaws in my approach?

Thanks

Christian