Doing some experiments with my XML-RPC code today, I noticed that calling "user.logout" seemed to be having no effect. I was able to create an authenticated session with "user.login", send some requests with it, destroy it with "user.logout", then continue to send requests with it. Looking in the sessions table, the session was still there and had the authenticated UID. I am requiring the session ID be passed as the first parameter of all XML-RPC calls.

Looking at user_service_logout in user_service.module, it seems to be destroying the temporary session generated by Drupal, not the session ID passed in as the first parameter of my XML-RPC call.

My quick hack to fix this is to call session_id() in services_session_load to set the session ID to the one passed into XML-RPC, then call session_id() again in services_session_unload() to set it back to the original session ID. With this change, when user_service_logout is called, it has the XML-RPC session ID set, and so logs that one out.

If that sounds like the right fix, I'd be happy to submit my patch; it's very simple.

Thanks!

CommentFileSizeAuthor
#2 services_logout.patch803 bytesscottgifford

Comments

marcingy’s picture

Hey post your patch and if we find an issue then we have a ready made solution. And you have investigated the issue and your proposed solution sounds good however being able to see the code will be helpful in determining if the approach is incorrect.

Marc

scottgifford’s picture

Status: Active » Needs review
StatusFileSize
new803 bytes
scottgifford’s picture

Sure, here it is.

mattman’s picture

Version: 5.x-0.92 » 6.x-1.x-dev

I'm changing this to version 6.x dev because this issue applies to the current HEAD as well.

For some reason (of which I currently can't dig deeper) Drupal's session handling in bootstrap is not killing the session (assuming that Services want's Drupal to handle it).

It would seem that since calls are initially assumed anonymous by Services (until authenticated), it might be a good idea on user.logout to explicitly call sess_destroy_uid() or sess_destroy_sid() from session.inc.

Does this make sense? Services is a service, it's not a user interacting via a web browser. Therefore, it seems as though it's "ok" to assume control of the sessions based on user logout actions.

Also, it would be an improvement for Services to manage it's own watchdog messages. Where currently, user_service_logout() uses.

watchdog('user', 'Session closed for %name.', array('%name' => theme('placeholder', $user->name)));

Where it would be easier to troubleshoot if Services would log messages under it's own domain. Plus, using the theme() function is adding silly html code to the log - which is unnecessary. I don't need to see <em>User Name</em> in the log.

While I can't roll a patch right now, I thought I would mention these things since this thread is here.

dereks’s picture

Possible fix -

Hello - I've been struggling with this as well. It sounds like the problem is the mx.rpc.AbstractService already has a logout method, so the logout command isn't making it to this module at all. There is a snippet on this web page in the third full paragraph:

http://sray.squidpower.com/2007/08/28/flex-2-java-session-log-out/

I saw another similar page from Adobe, but I don't have the link.

It sounds like simply renaming the function would do the trick.

HTH,
Derek

scottgifford’s picture

In my case at least, I can see from the logs that the correct function in Drupal is being called.

scottgifford’s picture

That is, when I add an error_log statement to the function, which I did while debugging, I can see it being called in the logs.

dereks’s picture

I'm new to Drupal, but I've been using Flash and Flex for years. In my case it seems pretty clear that the mx.rpc.AbstractService is getting in the way. Perhaps there is more than one issue to address here?

In Flex I am seeing the following. My RemoteObject id="user", and login works correctly.

1. If I add parameters to the logout function (session id and hash, etc), flex throws an error saying no parameters are expected with the logout function.
2. If I trick the compiler by using this["user"].logout(hash, domain, timestamp,nonce,sessionid) instead of user.logout(hash, domain, timestamp,nonce,sessionid) -- it compiles, I get this error in the AbstractService:

ArgumentError: Error #1063: Argument count mismatch on mx.rpc::AbstractService/logout(). Expected 0, got 5.

I hope this helps.
Derek

sitron2’s picture

hi dereks,
i dont think you issue has anything to do with this thread.

concerning your issue, snelson posted this in another thread:
For Flex reserved words, you can use the getOperation() method to call methods. So, since you can't do user.logout(), you do user.getOperation('logout').send(). Not as nice, but Flash/Flex really shouldn't have used "logout" as a method name.

where "user" should be replaced by your remoteconnection name. (and you can include the sessid as send(sessid))

dereks’s picture

Thanks sitron2 - that worked, Yay!

Still working my way through this. Sorry if I posted to the wrong spot.

marcingy’s picture

Status: Needs review » Fixed

Sorry this has taken me a while to look at it, @scottgifford the patch worked prefectly. Commited in d5 and d6.

scottgifford’s picture

Great, thanks!

marcingy’s picture

Status: Fixed » Closed (fixed)
rafalskalski’s picture

Version: 6.x-1.x-dev » 6.x-2.x-dev
Status: Closed (fixed) » Active

Hi guys there is still something wrong with this ... I'm using services with amfphp and when i send logout user is still on "online" list i can connect from different browser and login again with this same credentials ... then i have 2 same users logged in simultaneously... is sort of late and i was working all day ... maybe i do something wrong ? any help ...

rafalskalski’s picture

ok .... user_service_logout() - do not delete session from database

function user_service_logout() {
  global $user;

  if (!$user->uid) {
    // User is not logged in
    return services_error(t('User is not logged in.'));
  }

  watchdog('user', 'Session closed for %name.', array('%name' => theme('placeholder', $user->name)));

  // Destroy the current session:
  session_destroy();

  module_invoke_all('user', 'logout', NULL, $user);

  // Load the anonymous user
  $user = drupal_anonymous_user();

  return TRUE;
}

adding db_query('DELETE FROM {sessions} WHERE uid = %d', $user->uid); could help,

and ,

function user_service_login($username, $password) {
.
.
.
if ($user->uid) {
        //allow user to be logged in as many times as he wishes .... unless we 
        db_query('DELETE FROM {sessions} WHERE uid = %d', $user->uid);
}
.
.
.
}

tell me if i think right i'm php programmer new to drupal and i know you guys have your own ways of doing things ... maybe accessing db form here is some sort of sacrilege and i don't want to cause some holly war so please help :)

marcingy’s picture

Status: Active » Closed (works as designed)

session_destroy(); - destorys the current session and behaves as per drupal core (see the user_logout function in the user module). Plus in drupal multiple people can login using the same id at the same time. If you want to enforce this rule you would need to create a hook_user function of your own which performs the check for existing sessions when someone logs in.

kris digital’s picture

Hi,

I spent some time now getting an error when logging out from a flash site when I was logged in in the backend at the same time. user_service_logout always killed the wrong session and gave an error "couldn't session_encode().." or something.

I (seem to have) fixed it by using

sess_destroy_uid($user->uid);

instead of

session_destroy()

in user_service_logout()

Thank's mattman for the hint!

bricef’s picture

Same issue in 7.x version.

manolo.cruces’s picture

Hi,

I have an error with de logout service. When i need logout the user the system send me an error: FALSE (User is not logged in ...). But if i check de "sessions" table i can find this user.

Thanks.