Handling Multiple Presences in Openfire

buckets

XMPP is a terrific protocol for communications based media. For P2P networking, it is the or at least among the most robust. Well supported distributions like the ultralight eJabberd and extensive though somewhat resource intensive Openfire exist which implement the 20 year old protocol to a tee.

Still, there is that nagging need to detect multiple statuses at once to avoid overburdening resources with what could be thousands of extra requests. This article examines how to poll for multiple presences at once by extending Openfire’s presence service with a JSON plugin.

Code is available on my Github account.

Presence API

JiveSoftware, creator of the presence plugin, created a decent and simple presence API whose code is available on Github.

This API is easy to extend.

Using my plugin

My plugin simply adds a few lines to the PresencePlugin class and creates a JSONPresenceProvider class that can be used to return one or more statuses.

The available options are:

  • jid: Takes presidence and obtains the status of a single JID
  • jids: A semi-colon (;) separated list of jids of which to obtain statuses
  • type: This should be json to obtain the list of statuses

For instance:

http://myserver:9090/plugins/presence/status?jids=user@server;user2@server&type=json

This allows GET requests to be kept fairly simple. The same parameters may be used in a POST request as before.

Values are returned in a JSON object containing an array of user information objects:

{
  "presences":[{
     "user": "username",
     "jid": "username@server",
     "status": "[available | unavailble | etc.]"
  }],
  "success": [true | false]
}

Building

Building the plugin is simple on Linux (or Windows). Simply execute the following on Linux at the root of the project.

 mvn clean package
 cd ./target
 mkdir build
 mv presence*jar ./build
 cd ./build && jar -xvf presence.jar && jar -xvf presence-X.X.X.jar
 mv *jar ../
jar -cvf presence.jar .

This will combine the dependency and code jar into a single jar which can be placed in the plugins folder of Openfire. Openfire automatically detects new plugins.

Conclusion

Extending Openfire is simple. This article reviewed my modification to the presence plug-in allowing users to obtain the status of multiple JIDS at once through JSON.

Two Step Verification in a Flask REST App

flask

Flask is great. It is simple, easy, and allows for lightning fast deployment. However, there are a few security problems that should be worked out before using it in production.

This article examines how to deploy two step verificatiom and ip and mac address tracking alongside JWT tokens in Flask.

Code for this article is on my Github.

OS and Hardware Security

Software is just a series of electrons floating around the Internet. Fans, special devices for man in the middle attacks, and general human ignorance can all circumvent good practices.



Some things that should be done prior to development are:

  • Assign proper roles to users with appropriate security measures
  • Setup IP tables and other forms of firewall protection
  • Don’t randomly open ports to the world
  • Isolate unprotected devices from those handling highly secure data (a web server from your ETL servers for instance)
  • Ensure passwords are fairly secure (8-20 memorable characters avoiding certain others)
  • Use endpoint security such as RSA keys where appropriate

Proper Security

Like all things security, articles should not promote a version of encryption as secure or make claims using algorithms that could be rendered useless even as I write. All good algorithms sour

I can, however, provide a list of algorithms to not use:

  • bcrypt
  • blowfish

Remember, that all algorithms are usually broken. The US government currently lists AES as use-able and pbkdf can render sha512 useful. SHA512 is currently promoted as a good algorithm by NIST. 

JWT in Flask

JWT tokens are useful in that they store the information necessary to keep a user logged in. They are great for single page applications where session tracking might be in-appropriate. Know your use case.

A strong and configurable tool for implementing JWT keys in Flask is flask_jwt_extended which rides on the Flask-Security module.

Implementing JWT is fairly simple:

from flask import Flask
from flask_jwt_extended import JWTManager, jwt_required

app = Flask(__name__)
jwt = JWTManager(app)
jwt.init_app(app)

@app.route('/login', methods=['POST'])
def login():
    access_token = create_access_token(identity=username)
    return jsonify(access_token=access_token)

@app.route('/is_working')
@jwt_required
def is_working():
    return json.dumps({'Success': True}), 200, {'ContentType': 'application/json'}

It appears that Flask-Security was recently fixed so that password hashing works appropriately once again.

from flask_security import Security
from flask_security.utils import encrypt_password, verify_password

security = Security(app, datastore)
pwd = encrypt_password("test")
if verify_password("test", pwd):
    print("Verified")

Email Server

Before discussing two step verification, it is necessary to setup a test email server and be able to send emails. The smtplib offers the functionality of a web server in a simple configurable Python application. I personally printed out the input so will not post the code here. The Python docs are a good place to get started.

Sending emails can be done through smtplib or Flask-Mail. The smtplib library will be more flexible.

The following sets up a smptlib for sending an email:

import smtplib

....

host = email_config['host']
port = email_config['port']
email_server = smtplib.SMTP(host, port)
if email_config.get('ehlo', False):
    email_server.ehlo()
if email_config.get('start_tls', False):
    certfile = email_config.get('tls_cert', None)
    keyfile = email_config.get('tls_key', None)
    context = email_config.get('context', None)
    email_server.starttls(keyfile, certfile, context)
if email_config.get('user') and email_config.get('password'):
    user = email_config.get('user')
    password = email_config.get('password')
    email_server.login(user, password)
...
email_server.sendmail(recipient, [sender], msg.as_string())

Many different options are configurable using smtplib. These settings can be set using Flask-Mail but any code needed to help perform setup might be an issue.

Two Step Verification

It is now possible to extend the login function to include multi step authorization. The important pieces of the puzzle are obtaining an ip and/or mac address, verifying a password as shown, sending an email with a verification code, handling receipt of the code, and persistence.

Most of this is shown in my own open source project. This code uses uuid to generate a unique code:

import uuid
...
code = uuid.uuid4()

This code is hashed as before and stored using SQLAlchemy.

The basic process followed in my Github code is:

  1. Use login() to retrieve the JWT key and check for a matching mac address and ip
  2. Send an email verification code as needed
  3. Through verify_ip_code and verify_mac_code the code is validated and databases updated

The login function contains the majority of calls for two step verification.

Conclusion

This article examined the basics required to create two step verification in Python using Flask using examples and code from my Github repository.

It is important to use the most up to date algorithms. This article made no attempt to recommend an encryption algorithm.

A Neat Little REST Trick

So there is a shared memory problem. We are using the REST template and a few solutions come to mind. Perhaps it is time to not rule out statics.

The Controller component is established as a Singleton whose methods are called by every connection. It is possible to include a static synchronized static object to avoid. Java’s concurrent classes have a few of these. Synchronized classes and maps of locks are way more complicated and likely to slow things down. Synchronized methods in fact lock all Class level methods and attributes (e.g. synchronize(this)).

As a warning though, the CopyOnWriteArrayList is thread safe but slow for writing to.

The example below is of a ConcurrentHashMap<String,Integer> but the types are sometimes not showing, sorry.

@RestController
public class RESTClass{
    private static ConcurrentHashMap<String,Integer> mp = new ConcurrentHashMap<String,Ingeter>(); 
}