I ran into an interesting problem today. I'm using LoginToboggan with its pre-authenticated role, which lets users create an account and log in with limited privileges until they confirm their email address. Though this worked properly via the Web site, with the Services module users weren't restricted properly.
Restriction of pre-authenticated roles are implemented by LoginToboggan's hook_init, which removes users from the "authenticated user" role if they are in the pre-authenticated role; this effectively gives them anonymous rights, plus any rights explicitly granted to the pre-authenticated role.
This wasn't working with session IDs passed via XML-RPC, because at the time hook_init is called, we are still an anonymous user. When we switch the session in services_session_load, the new user is loaded, but hook_init isn't called again, so they remain in the authenticated users group and are not restricted.
My solution to this was to call logintoboggan_init at the end of services_session_load, but obviously that's a hack.
I'm not sure of a better solution, or whether it lies in Services (which maybe should call hook_init again after switching the session?) or LoginToboggan (which maybe should find a different hook for this).
Comments
Comment #1
marcingy commentedI'll be honest as logintoboggan isn't part of core I would say that services shouldn't worry about it but given that this could impact a sites a lot my I agree that we should look to call hook_int (and hook_boot in d6) otherwise we are in the situation whereby drupal can't respond to hooks corectly - usless of course we can move can move the session_load code to services_init???
Comment #2
scottgifford commentedYeah, I agree, something logintoboggan-specific is not appropriate, but the general problem of what session you have when hooks are called is probably worth solving.
Installing Services with a very low weight and changing the session in hook_init sounds like it would work. Is there enough information when that is called to switch the session?
Comment #3
marcingy commentedI think the hook_init approach is going to be problematic to say the least due to, infact I'm not even certain we have the data available from the xml-rpc call at that point in time well not without doing something complex to pull it. I'm tending towards a simple solution along these lines:
In the case of D6
and D5
Then any actions will be performed against the correct user object my only concern with approach is that it going to result in certain code being excuted twice.
Comment #4
scottgifford commentedYeah, exactly, I'm not sure whether executing code twice will cause problems or not. It could certainly have a performance impact.
I wonder if it's possible to intercept things earlier in the process somehow? Maybe a .php file that runs instead of Drupal's core, which could extract the session then jump into Drupal's bootstrap code?
Comment #5
marcingy commentedActually i'm thinking the easy way to do this might infact be to provide a hook after the new session has been created that will then allow a custom module to then manipulate the user object as required based upon the install that they have so effectively a hook_services_user_alter. That way the module can selectively excute any hook_init code or can remove roles etc.
Comment #6
scottgifford commentedHrm...I suspect the logintoboggan folks might be as reluctant to put Services-specific code into their module as you are to put logintoboggan-specific code into Services.
Comment #7
marcingy commentedI'm not suggesting they do that, all I'm suggesting is providing a hook that a developer can leverage as required and then manipulate and set up any 'special' rules for sessions on their site. This might not be ideal solution but it would provide a cleaner way for service developers to manipulate code.
Just spent 10 minutes looking at code and the hook_init approach might work however it depends on whether or not xmlrpc_server_get() is none destructive.
Then in the xml-rpc server we can basically check to see what authenication methods are enabled and then pull the appropriate session id out for the method in question. A parameter would be added to function xmlrpc_server_server($session = FALSE). This would then allow xmlrpc_server_xmlrpc to be mapped to different call back. The new call back would then do the following:
* Check if keys are enabled and strip off those args
* Check if sessions are enabled if so pull and return that value else return NULL
If this idea seems valid I'll try and get a patch rolled.
Comment #8
marcingy commentedOf course if that is a problem we can put the values into a global... To clarify the call to xml-rpc being destructive.
Comment #9
scottgifford commentedAh, I see, I misunderstood what you were proposing in #5. Your approach in services_init looks like a good one if it will work.
Comment #10
voxpelli commentedFor reference - here's the issue for LoginToBoggan where their solution was reached: #92361: The pre-auth user feature does not work properly
To extend on what was suggested in #5 - instead of adding it to Services I would suggest to create a new non-services wrapper module for the loading and modifying of session users. Such a wrapper module could expose a hook and an alter for modifying the session-loaded user and could execute that in both its own hook_init() and in new method that could more or less replace services_session_load(). Such a module could be supported by LoginToBoggan, Organic Groups and all other modules that need to load or alter data on the sessions' user-object.
This issue is bigger than just Services and should be solved in a way that can be reused by other modules - and perhaps even included in a future version of core.
Since this isn't really a bug in Services (rather a bug in LoginToBoggan) I'm changing this to a feature request. I'm also changing the version since all development should happen at the latest version and then be backported if needed in older versions.
Comment #11
kylebrowning commentedThis is fixed in 3.x and we will not be backporting to 2.x.
If its it remains an issue you cannot work around, post a patch and Ill be happy ot review it.