Project

General

Profile

Best/most efficient way of unauthorizing/logging out a user?

Gureen Ryuu
Added almost 5 years ago

In the server I'm currently developing, users need to have authorization/subscribe to a 3rd party API, in order to be able to login and then chat to other users. The 3rd party server will call our own server and signal to us any changes in the authorization.

My question is, what is the best way to handle this authorization in Tigase? Looking at the database tables, I can see that the tig_users table has an account_status field. Can this be altered to reflect authorization? I've tried setting it to 0 and this stopped the user from logging in, returning to him that he's not authorized.

However, I do not know whether or not this is the right way of doing things. Aside from that, when the user was already logged in (and I guess this is the main question), if I changed his account status, he was still able to chat normally.

What is the best way to de-authorize his session? Is it through a plugin like the message plugin, who checks the database every time it gets a packet from this user to see that he's authorized? Or is that too inefficient and will slow things down? I also see that the plugin has access to session and repo variables, but I haven't been able to figure out how to use them to get the authorization info..

Or maybe it's through a component that runs a certain number of times an hour and logs out unauthorized users?


Replies (11)

Added by Wojciech Kapcia TigaseTeam almost 5 years ago

The db field is only for enabling/disabling the account, the changes won't be applied to current sessions.

How exactly is the integration with 3rd party done? Depending on that you could issue a tigase.server.Command.CLOSE to all opened resource connections forcing them to close.

Added by Gureen Ryuu almost 5 years ago

They call a HTTP (php) API that updates the database.

Though if there is a better way we might be able to change that, depending on the alternative solution.

Added by Gureen Ryuu almost 5 years ago

I'm going to try and reformat my question into something more clear I suppose:

Is it advisable, as in, it won't slow down performance horribly, if I access the database inside the "process" method of a plugin that implements XMPPProcessor?

For example if I access the database to insert additional info sent in the message's extensions, would that slow the plugin down a lot?

I was reading up on the DataRepositoryImpl and how I should use it instead of using JDBC if I want to access the database? I've tried using it but I wonder if it's advisable inside such a frequently called method.

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam almost 5 years ago

There are some plugins which access DB already such as plugins responsible for user login, offline message retrieval, etc....

Of course accessing DB in plug will slow it down considerably. If there is no DB access XMPP packet processing usually takes less then 1ms. With DB access, well, it depends how has is the DB but in the best scenario 10ms if you are reading only. If you write to DB then it make take even 100ms.

Whether this is a problem for you or not, it depends on your system. The time needed to process XMPP packets limits your system throughput. If you have 10 messages per second on your system and each message takes 100ms to process, then your system reached it's processing limits. But if 10 messages per second is the max you expect on your system this should be fine.

However, we have installations which experience load of 500k packets per second (yes half million packets per second). Doing any DB while processing such a traffic is not realistic.

Added by Gureen Ryuu almost 5 years ago

I see. So then it's a horrible idea to access DB on packets that are frequent, such as chat messages. I'm still not quite sure about the load on the server, but early estimates are around 100k-500k users.. not sure how many packets that will generate per second, but it's certainly more than 10! Then checking if the user is authenticated in every message from the DB is out of the question then..

Does the message archiving plugin (not offline, but always) have the same problem as you described above?

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam almost 5 years ago

Gureen Ryuu wrote:

I see. So then it's a horrible idea to access DB on packets that are frequent, such as chat messages. I'm still not quite sure about the load on the server, but early estimates are around 100k-500k users.. not sure how many packets that will generate per second, but it's certainly more than 10!

We usually estimate that, depending on the system, 1% - 10% online users are in an active chat, which means they send a message every 10 seconds. This gives you traffic of 100 - 1,000 messages per second for 100k online users. Tigase can usually handle about 10k packets per second per single CPU core.

Then checking if the user is authenticated in every message from the DB is out of the question then..

You do not need to do this. Tigase already does this for you. Tigase already checks whether the user is authenticated when processing each packet from/to user. However, it does not uses DB for this.

Does the message archiving plugin (not offline, but always) have the same problem as you described above?

Yes, this is why we do not do this in a plugin but in a component. The plugin just forwards messages for archiving to a component.

Added by Gureen Ryuu almost 5 years ago

Thank you for all that data! It's quite useful in estimating just how much load we might have.

Artur Hefczyc wrote:

You do not need to do this. Tigase already does this for you. Tigase already checks whether the user is authenticated when processing each packet from/to user. However, it does not uses DB for this.

Can I ask how it does this? I can see it's through the active sessions

@ session.getActiveSessions()@;

But I can't figure out how to alter the active session to de-authorize the user from there, so that it throws the NotAuthorizedException , since altering the database doesn't work on the current sessions.

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam almost 5 years ago

Gureen Ryuu wrote:

Thank you for all that data! It's quite useful in estimating just how much load we might have.

Artur Hefczyc wrote:

You do not need to do this. Tigase already does this for you. Tigase already checks whether the user is authenticated when processing each packet from/to user. However, it does not uses DB for this.

Can I ask how it does this? I can see it's through the active sessions

@ session.getActiveSessions()@;

In the plugin's process method you get XMPPResourceConnection object. It has a method: isAuthorized() which returns true if the connection/user is already authenticated.

But I can't figure out how to alter the active session to de-authorize the user from there, so that it throws the NotAuthorizedException , since altering the database doesn't work on the current sessions.

The same class XMPPResourceConnection has method: logout() which you can call to "de-authorize" user's connection.

Tigase usually does not access database at all unless this is absolutely necessary. All the data are stored in memory. Otherwise it would be impossible to handle traffic of 500k or more packets per second that we have on some installations.

Added by Gureen Ryuu almost 5 years ago

Sorry for the late reply, holidays and all!

My apologies, rereading my previous reply, I seem to have not formulated it correctly. I'm already aware of the things you mentioned in your post.

My question was, to be put briefly: How can I access a user's XMPPResourceConnection and session variables from outside the plugin, for example, from a component? Here is the scenario we have planned, though I'm not sure if it's possible: The third party will call our server through an HTTP/PHP API, and this API will then send an XMPP message to a component in the server that will de-authorize the user and force a logout.

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam almost 5 years ago

You cannot access user's session data outside of the SessionManager and plugins API. This separation of data is intentional and there are many resins behind this architecture design.

Your workflow is almost correct but incomplete. I do not fully understand what is the exact role of this component, how much logic is in there but assuming it makes some decisions and other checking before deciding what to do next. Then this component is necessary. However, to disconnect a user the component should send a command to SessionManager requesting user disconnection. SessionManager has access to all user's data and can perform the requested action.

If this your custom component role is purely to execute your admin commands then, most likely you do not need it. You can send the command form REST API directly to SessionManager to perform any action on a user you with.

By the way, you know that Tigase offers REST API for administration tasks out of the box? Also, you know about admin framework and scripting API in Tigase?

Added by Gureen Ryuu almost 5 years ago

Artur Hefczyc wrote:

You cannot access user's session data outside of the SessionManager and plugins API. This separation of data is intentional and there are many resins behind this architecture design.

Your workflow is almost correct but incomplete. I do not fully understand what is the exact role of this component, how much logic is in there but assuming it makes some decisions and other checking before deciding what to do next. Then this component is necessary. However, to disconnect a user the component should send a command to SessionManager requesting user disconnection. SessionManager has access to all user's data and can perform the requested action.

If this your custom component role is purely to execute your admin commands then, most likely you do not need it. You can send the command form REST API directly to SessionManager to perform any action on a user you with.

By the way, you know that Tigase offers REST API for administration tasks out of the box? Also, you know about admin framework and scripting API in Tigase?

The component will interface with the API. Once the API gets that a user has been unregistered and unauthorized, or for example, the user wishes to delete his account with the 3rd party API, for example, the API will message the component who will in turn handle it by altering the user's session. It's for admin commands, I suppose, but they're automated rather than manual commands. However I was thinking of making it into a plugin instead of a component since I can access the session from there.

But after reading your post, I will try to read abiyt the REST API provided by tigase to try and do this instead of using a component.

    (1-11/11)