Change status of an XMPP user in Django using ejabberd - python

I want a Functionality where If a user change his status, that status needs to reflect at runtime (like Whatsapp). My App is in IOS and Android and backend is in Django.
I am advised to use ejabberd server for this as tt supports XMPP protocol.
I am not sure how to implement this functionality. Can anyone guide me?

There is many ways in XMPP to express the state of the user:
presence: It allows you to convey both the availability of the user (among predefined "show" elements: Available, Away, Do not Disturb, etc) and your status (Free form text). However, presence is related to the user session and suppose he has an XMPP session open (and thus is connected). It means it is intended to be set by user from client, not from backend and is only broadcast to contacts when the user is online.
Last activity: This is something that complement XMPP presence. It is a way to get user state information when the user is offline. I would recommend to use that to get more familiar with XMPP. To integrate with your back-end, I would setup ejabberd to store last activity in database and to update it in database from your backend. User that need to read it (For example when a conversion tab is opened) can display the XMPP if the user is online, or the last activity if the user if offline. You can also just let the user set its own status on last presence when getting unavailable (offline). It will be automatically updated in the last table by ejabberd.
mood: This is something used to express state in a more complete way. User can set mood with more richer status and the mood is not tight to presence. However, it is a bit more complex to integrate with backend as it is based on the PubSub protocol.
To summarize, in your case, you can use a mix of standard XMPP presence and Last activity with change of status from backend.

Related

What is different between "DRF Throttling" and "Django Axes"

The "Django-Rest-Framework (DRF) Throttling" can help to prevent bruteforce attacks and failed login attempts.
Then why do we need to use "Django axes", "Django defender", "django-ratelimit" or similar components?
Thanks In Advance
Throttling, as provided by DRF, is very different to Authentication, which is the focus of Django Axes.
In DRF you can allow access to your resource (say a database) for a defined amount of times (i.e. 100 database lookups) in a given period (lets say a day), so they are throttled to that amount/period, here 100/day. In some use-cases the user need not even identify themselves necessarily to avail of your service, there is no authentication involved -here you look at the IP of the users system as a key to throttle the users activity. Yes you can run throttling in conjunction with authentication in DRF, but one does not require the other.
Whereas in Axes you are primarily concerned with having the user prove his identity (authentication) through the login process. You can also instruct Axes to deny a repeat-failing user the opportunity to authenticate, i.e. if you fail to login correctly for 10 attempts you are now banned from logging in for the next 5 minutes. So typically a non authenticated user will never avail of your service and a repeat authenticate-failing attempts will result in that IP being denied the opportunity to authenticate for an extended time period. The emphasis with Axes tends to be on determining why a user failed to authenticate and by which means they gained access to the system. For example from the Axes reports, you can determine how many users logged in that day using the link emailed to them from the registration page. Or which users logged in using facebook, and also how many users failed to login (IP, username or email for example).
Furthermore, DRF is in effect an add-on to "regular django", and thus it´s throttling and authentication are tailored to the API service that it performs. Your users using an API are in general not likely to authenticate manually to the API but rather using some token (JWT,csrf) . Django Axes is also an add-on to regular django and typically services the needs of a typical web site with authenticating users. You can use both services, DRF and Axes on the one django platform, they work well together and do not clash.
As far as I know, those libraries you mentioned all do the same thing (with a few differences between them). You can choose the one which best suits your needs.
If you are using DRF, then you don't need an aditional library (axes, ratelimit, etc.) because DRF already has the throttling functionality build in.

send ejabberd push notification ( django )

I have integrated ejabberd for chat functionality. Apps backend is in python-django and frontend is in IOS. current flow is as follows :
When user signup into my app, A record has been created for that user in ejabberd server. This thing is handled in backend. unique id for that user is the combination of primary key and name ( e.g - 123_mark#xyz.com )
To chat on frontend , IOS is using these id's. When both users are online , they can chat successfully.
Problem - When a user gets offline or a user kills the application, Then backend has to send notifications to device. I have checked ejjaberd's documentation. According to them I have to use mod_zeropush to send notifications. I have checked some articles, but I am not sure how to send notification to users. Can someone explain it in detail.
As far as I can see ZeroPush mod leverages a ZeroPush server, I might be wrong about this as I just glanced through their pages.
What you need to do is to create your own mod which hooks into events that are occurring in ejabberd. This Q&A sums it up: How to develop custom functions on top of Ejabberd?
Basically you need to find out which event is fired when a user disconnects and hook into that event so your mod would be executed.

Get list of connected users with Django

I'm looking for a way to keep track of users that are online/offline. So if I present all users in a list i could have an icon or some kind of flag to show this. Is this built in in Django's default Auth system?
My first thought was to simply have a field in my profiles called last_logout in the models and update it with the date/time each time user logged out.
With this info and the built in last_login I should be able to make some kind of function to determine if the user is loggedin/online right?
Or should I just have a boolean field called "online" that I can change when user logs in and out?
With only django it will be hard to do. For such task async frameworks are more suitable.
For example, tornado.
Users won't do logout explicitly every time they go offline. They just close their browser and that's it. You can't know it with only django auth app. It is not designed for such tasks.
Even if you will check for not expired session, it not gives you all online users, because session can be non-expired for 30 days.
So to get real online users, possible solutions are:
Every user will send some data via javascript to your server, for example every 10 seconds. You can fetch that data on server and put user into cache and set cache key to be alive for 10 seconds. So when you need to know, who are online now, you'll check your cache. But it is not a good solution, because it will need a lot of server resources.
Use async framework (tornado) at server side (you can setup separate process for exact requests). And use websockets (SockJS is a good library for that at client side). It is a more complicated solution, but it is better.
You have to consider what exactly means for the users to be "online". Since any user can close the browser window any time and without the server knowing about that action, you'd end up having lots of false "online" users.
You have two basic options:
Keep track of the user's last activity time. Every time the user loads a page you'd update the value of the timer. To get a list of all online users you'd need to select the ones with an activity before X minutes. This is what is done by some web forums.
Open a websocket, long polling connection or some heartbeat to the server. This is what Facebook chat does. You'd need more than just django, since to keep a connection open another kind of server-side resources are needed.

How to register an oauth2 client?

I'm writing an oauth2 provider and am not sure how to implement client registration. The oauth2 specification doesn't cover this aspect:
The means through which the client registers with the authorization server are beyond the scope of this specification but typically involve end-user interaction with an HTML registration form.
Moreover, the oauthlib documentation has the following to say about the Client data model:
It is common practice to link each client with one of your existing users. Whether you do associate clients and users or not, ensure you are able to protect yourself against malicious clients.
Now I sure would love to protect myself against malicious clients, but how can I link a client to a user if registering a user requires a registered client?
The oauth2 spec again has something to say about this, but it's very cryptic:
Client registration does not require a direct interaction between the client and the authorization server. When supported by the authorization server, registration can rely on other means for establishing trust and obtaining the required client properties (e.g., redirection URI, client type). For example, registration can be accomplished using a self-issued or third-party-issued assertion, or by the authorization server performing client discovery using a trusted channel.
Questions
How should a client be registered if linking to a user is required, given that registering a user requires a registered client?
How should a client be registered if linking to a user is not required? What is meant by 'redirection URI, client type, and third-party-issued assertion?
When answering this question, I am going to assume there is already an access control framework that this provider will be attached to, and the application that will use this provider will have HTTP access and has capabilities to handle HTML forms, as no details on this whatsoever were provided by the question (i.e. what framework is this provider going to sit on, or is it something completely naked and standalone on some homebrewed framework).
I'm writing an oauth2 provider and am not sure how to implement client registration. The oauth2 specification doesn't cover this aspect:
The means through which the client registers with the authorization server are beyond the scope of this specification but typically involve end-user interaction with an HTML registration form.
While it doesn't spell it out explicitly, it did suggest that typical registration of a client involves end-user interaction with a form. If you see how others have done it (such as through imgur's API, OAuth 2 user documentation) you will find that it provides a Registration link and hey that's how clients are registered. No OAuth 2 is required as you are already authenticated via the browser.
Now I sure would love to protect myself against malicious clients, but how can I link a client to a user
By linking your server applications's representation of the client details to the user (tracked by some system) that created those client details? It's not like user specific data suddenly becomes more mystical just because it is used for authenticating an OAuth2 client. If you find abuse related to access using those client details (from your logs) you could just revoke those credentials related to that client, and punish the user that own that client. (Unless it's their clients... erm, your other users using that client is doing the abuse but you should be able to see that, right?)
if registering a user requires a registered client?
If you really want to have people register their clients using their client before they register their client, that's pretty much madness (i.e. a chicken and egg problem that shouldn't need to exist). Nowhere in the specification this was ever suggested that they are mutually inclusive problems. Here, to simplify this:
You can use a registered client to register a user
You can register a client to a registered user
Those two things are completely separate from each other. You have to have one before the other (actually, you can create a user registration form that also generates a client credentials at the same time, but I digress), but really, a registered client is essentially reducible to some credentials that are shared between that client and the provider it is registered against.
You can make your own registered clients, too, since you have full control of the provider, you can inject any credentials that will be used by that registered client of yours to do whatever you need, including registering new users, but...
How should a client be registered if linking to a user is required, given that registering a user requires a registered client?
You know you can just register a user using a standard HTML registration form? Just use the user registration form that the framework provided, or write one* if that framework doesn't already provide one.
How should a client be registered if linking to a user is not required?
When I implemented an OAuth1 provider for Plone, client registration can only be done by administrators/managers of the site, so not something user can do, thus someone has to contact the owners of the site to find out how to do it. This generally removes the security problems associated with not linking clients to users (since clients are now linked to actual people coding those clients up who are not necessarily users of the site through external means).
I realized I did not really answer this question, but this is really up to your implementation and what needs/restrictions you decide to limit/provide. I mean you can have a totally anonymous form on your site and let it rip, but I don't think you want that as that weakens security of your application dramatically.
What is meant by 'redirection URI, client type, and third-party-issued assertion?
If you go to the sections as specified in the RFC, you will find answers there:
Redirection URI
There is actually quite a lot of ways to subvert the security of your users' (resource owner's) data if this is not carefully understood, but is used by the authorization server to "redirects the resource owner's user-agent back to the client", as the authorization is done on the authorization server which is part of the provider's infrastructure. So in general, the client has to let the authorization server know where/how it gets back to itself after the resource owner authorizes the client's access through this redirection URI. However, if the redirection URI specified is not verified, security issues can and will happen.
For instance, native applications (a client profile of the client type public) will (used to, I am coming from an OAuth1 background) have the complete client credentials embedded inside the application, which will be extracted by hostile attackers in a bid to masquerade as a legitimate web application (another client profile, but can be considered as a confidential client type) that makes use of your application's services. Once the hostile attackers are up and running they will entice your users (resource owners) to use their masqueraded site, and grant the masqueraded site their access tokens through your authorization server and if redirection URIs are not validated, it will redirect your users (resource owners) to the attacker with the authorization code (as outlined in section 1.3), giving the attacker access to your resource owner's data.
That was the easy common case - another problem case is that your other web application client might have a credential leak without them knowing, resulting in this exact scenario.
Hence this is why they suggest that you should only "redirect the user-agent to the client's redirection endpoint previously established with the authorization server during the client registration process... after completing its interaction with the resource owner", which can mean that only the domain name registered to that client will be legitimate redirection targets, otherwise something went wrong and your authorization server aborts and does not provide the authorization grant.
Client Types
Again, just read/scrutinize all that carefully.
Third-party-issued assertion
As opposed to self-issued client registration done kind of like a client registration form, your application might delegate the client authentication to a third party which will do the verification for you. If you have to worry about this and don't know where to start I suggest you ignore this and just only do self-issued client.
* Are you really sure you want to write an OAuth2 provider without any underlying user/ACL framework for you to hook this to? I mean you can write one but you should really build that part first before you worry about OAuth2 (again, I am not making any assertion, since the question provided no information on this).
Now, if you are not doing this as part of some existing framework but just something standalone that you want to toy/try out as learning, I strongly suggest you to pick something else because this is probably beyond what you can do in a correct manner. Especially if you don't already fully understand the implication of this with regards to the underlying ACL and security of the resource owner's data, and other related stuff.
No offense, but these things are very very difficult to do correctly. Even the bigger companies have had security issues with their OAuth2 solutions.
Finally, speaking from experience, I spent about four (4) weeks (!) staring at the OAuth1 specification years ago, using a poorly written Python OAuth library (later replaced with oauthlib, which is much better) in an attempt to build an OAuth1 provider on top of Plone, before I got a single line of code directly related to the provider committed. A lot of junk/trial code written was thrown away, and this was done because understanding all of this stuff actually took time (granted, I was not exactly working full time on this, had other responsibilities too which was distracting me from this). Another part of the time was spent trying to understand how the user/security stuff is put together at the Zope/Plone layer. Granted I was still relatively new to that side of that framework, but I can guarantee you that this road is not going to be easy... however I did seem to find that OAuth 2 cleaned things up in some ways to make it easier to understand, but find that the security may have been weakened. That said, I currently have no immediate plans to port my Plone addon to support 2.0 as my sponsors does not require that, so there may be things I suggested up there that may differ slightly from 2.0. Would love to hear your comments if others have read this far. I wrote way more words than I originally intended to, oops.
Anyway, good luck on your adventures.
Additionaly for dynamic registration, please go through this spec as well
https://www.rfc-editor.org/rfc/rfc7592

XMPP based live-chat system in Django

I need to implement an XMPP based live-chat system in Django. After a lot of scourging and ideas from a colleague, we came up with this.
Method using a bot:
When a visitor visits the site. The visitor's XMPP client which in this case is Strophe.JS begins an XMPP-over-BOSH connection to the XMPP server and connects to a room called <visitor_id>#conference.demo.com. Currently there is no one else in the room.
The visitor makes an analytics request with a custom visitor id to Django
The Django view, stores the visitor id in a table called ActiveUsers. This table contains a new field as well called status. It sets the status to INACTIVE.
This model dispatches a signal on the save method.
This signal gets picked up by a bot which connects to the XMPP server and joins the room <visitor_id>#conference.demo.com. Now we have the user and the bot in the room.
The site support people are logged into their web interface.
They have JS code that keeps long-polling the Django site to check the ActiveUsers. It fetches the rows from the table and displays it. (I've thought of using django-pubsub for this)
When the visitor types a message, it goes via XMPP-over-BOSH to the XMPP server, the jabber bot in the room see this message and updates the status of the record in the ActiveUsers table to ACTIVE.
As said: The site support people have JS which keeps polling this table. It begins blinking the ow to show that the user is now chatting.
The support personnel can now double-click that row which on doing so begins an XMPP-over-BOSH connection to the visitor's room. It knows that the room is <visitor_id>#conference.demo.com.
The bot seeing that the support person has joined the room, updates ActiveUsers record to show CHATTING. This ensures that no more than support personnel can be in the room i.e. room occupied.
The bot logs the messages to a Django table
When the both sees that both users have left the room, it deletes the record.
ejabberd or openfire will be XMPP server.
Apache is the web server which runs mod_wsgi for serving Django and mod_proxy for proxying the XMPP-over-BOSh requests to the XMPP server.
Does this sound like a good of doing this? Any suggestions? I'm worried about the load on the Django system.
(It's long. Sorry 'bout that.)
Method using Presence Stanzas:
On the client side, i'm using Strophe JS library which supports presence and I had add callback methods. I'm flexible with using ejabberd or openfire as my XMPP server. The are many visitors on the XMPP server — some from site A and some from site B but they are all connected to the same XMPP server. When the visitor visits the site, they are connected to the XMPP server as <visitor_id>_<site_id>#demo.com and each one gets logged into a room called <visitor_id>#conference.demo.com. The sales/support personnel are also connected to the XMPP sever as <supportsale_id>_<site_id>#demo.com. They are not connected to any chat room though. They don't have any of the visitors on their roster.
A good way of showing that a user has connected to the site would be to pass a presence stanza to the sales/support people. Only visitors and sale/support personnel from the same site communicate with each other and that's why I have the <site_id> in the username to show which site that person belongs to.
It seems that you can't subscribe to presence stanzas for a user if you don't have him on your roster. (Quite logical). Is is possible to automatically add every new user of a site connecting to the system to the roster of the sales/support people of that site? Wouldn't this then automatically signal a presence to the sales/support people? How can I implement this — any help?
I wrote exactly this. It's called Seshat and uses a "broker" bot between the website and a Jabber server (I use ejabberd). It's in beta right now mainly because it hasn't been extensively tested outside my company.
Note: while the README specifically mentions the Pyramid web framework, the core system would work just as well with a Django, TurboGears, or command line system. It's just that I only package example code showing how to integrate it with Pyramid.
Seshat is being actively developed. If you have any feature requests, let me know. :-)
I'm not sure you need to use MUCs to implement this. Your bot could maintain its own pubsub node which it is subscribed to. When a new user begins to type it could send a notification to the pubsub node, which the bot would then see. From there, the bot could notify a support person via XMPP, thus eliminating the need to long poll the database table. Then the support person could start a standard one to one chat session with the end user. In addition, their presence could be set to 'na' in order to show that they are in a session with a user.
I think that it's better to use presence stanzas to "signal" any (in)activity. What you need to store in database is only the persistent data you need for further analysis. Otherwise, I think you'll have great time coding the application :).
EDIT:
function onConnect(status) {
if (status == Strophe.Status.CONNECTED) {
var joined = false;
var participants = {};
$('#events').html('<text class="textmainleft">XMPP connection established. Ready to rock n roll!</text>');
connection.send($pres().c('priority').t('-1'));
connection.addHandler(notifyUser, null, 'message', 'groupchat', null, null);
connection.send($pres({to: 'groupchatroom#conference.demo.com/' + nickname}).c('x', {xmlns: 'http://jabber.org/protocol/muc'}));
} else if (status == Strophe.Status.AUTHFAIL) {
$(location).attr('href', AUTHFAIL_URL);
} else if (status == Strophe.Status.CONNFAIL) {
$(location).attr('href', AUTHFAIL_URL);
}
}
$(document).ready(function () {
connection = new Strophe.Connection(BOSH_SERVICE);
connection.connect(jid, password, onConnect);
});
notifyUser is another function (just link onConnect) that would handle the received message stanzas.

Categories

Resources