Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile

An adapter-like pattern and code for the creation of XMPP users in an OpenFire server

0.00/5 (No votes)
14 Dec 2015MPL6 min read 12.7K   68  
PHP code and pattern for the creation of OpenFire XMPP users from end-user applications via HTTP POST

Introduction

This article provides an adapter-like pattern, and code that can be used in order to:

  • Create OpenFire XMPP users, using HTTP POST.
  • Restrict access, to a subset of allowed OpenFire REST API operations, to certified clients.
  • Verify the created user's mail.
  • Set, to a sufficiently random value, or reset the user's XMPP password.
  • Allow access to this REST API subset operations, only to client applications, which have access to a Client facing token.

The pattern presented in this article, solves the problem of automatically creating users from within authorized XMPP applications. Alternatives, such as the XEP-0077 in band registration, are prone to spammers and non controlable registration of new users. Web based alternatives, such as the OpenFire Registration Plugin for creating users through a web registration page, might not be suitable for all applications:

  1. They can not support automatic registration, without end user intervention, and,
  2. Registration cannot be restricted to authorized applications.

The code described later, restricts access to a selected subset of allowed OpenFire REST operations by distrubiting a Client Facing token. This should be distributed with care, since it enables anyone with access to the token, to create users.

 

PHP code  presented here, is configurable, and has been tested in an Azure web site application. The architectural pattern presented, can be applied and reused, for the controlable registration of new users to  any XMPP server, which features an HTTP based administration interface.

Background

XMPP is a shortcut of Extensible Messaging and Presence Protocol, which is an open standard communication protocol for message-oriented middleware based XML. XMPP is used extensively for human to human communication, in Instant Messaging applications, but can also be used for Internet of Things apps, and for machine to machine distribution of messages, presence information etc.

The Openfire XMPP server provides a REST API for the management of the Openfire XMPP server. This API provides methods for adding, deleting, modifying users, groups, giving the capability to fully administer an Openfire server. However, giving access to this API, means that the service accessing, it gains administrator level access to your Openfire server. If this is a trusted, shielded from the public, service this is acceptable.
Thus this REST API must not be used directly from an application to be distrubuted over the Internet or from a Client facing application at no time. E.g. allowing access to the REST service, from a mobile app, distributed over a app store, must be avoided at all costs. If the connection Token is discovered, reverse engineered or leaked, a potential attacker will gain access to fully administering the XMPP Openfire server.

Thus a HTTP client facing adapter service is required in order to:

  1. Limit end user access to a subset of the REST API. Current implementation provides only create and password reset  operations, accessible to an end user application.
  2. Restrict the distribution of the REST API  service authorization Token. End user applicaction gains access to the service using a separate client facing Token. While this poses some security risks, even if leaked it can potentially provide access only to the creation of new users, with verified emails, and to reset known users password.
  3. Verify users' email. Users are created with a temporary random password, which is send by email, thus confirming the email.

Sending in plain text the user's password is not the best available option, and should be treated only as a temporary one time password by the end user application. The user should be forced to change this one time password, upon using it, from the end user application.

It can be made more secure and expanded in the future, by sending a one time password reset link to the email, instead of the temporary XMPP password.

In this solution configuration and connection string variables are read from the environment. These are set an Azure PHP Web App, App Settings and Connection Strings, configuration variables. . The SendGrid service is used in order to send the confirmation email.

Below you can find a draft functional block architecture of the pattern under description.

Draft functional block

Dependencies

Dependencies are resolved using the Composer PHP dependency manager. The adapter requires these packages:

  1. The php-openfire-restapi, a simple PHP class designed to wrapp the Openfire Rest Api plugin functionality. This class provide full access to the REST API, and it is not suitable for use by an end user client application.
  2. The sendgrid PHP library, for using the SendGrid service.
  3. The paragonie/random_compat library in order to generate a sufficiently secure temporary password. 

Using the code

In order to use the code simply:

  1. Download the attached userMgtAdapter.zip file and extract it.
  2. Place the userMgtAdapter.php file and the composer.json file in your selected PHP app location.
  3. Run Composer in order to resolve dependencies
  4. Define the following environment variables:
    • APPSETTING_SHARED_SECURITY_TOKEN, the security token, that a client end user app can access the userMgtAdapter service.
    • APPSETTING_API_HOST, the XMPP Openfire server host
    • APPSETTING_API_PORT, the XMPP Openfire server port the REST service listens. Please note that this is only over SSL.
    • CUSTOMCONNSTR_API_SECRET, the API secret for connecting to the Openfire REST service
    • APPSETTING_FROM_EMAIL_ADDR, the email to send the verification message.
    • CUSTOMCONNSTR_EMAIL_API_SECRET, the SendGrid API secret.
    • APPSETTING_CREATE_EMAIL_SUBJECT, APPSETTING_RESET_EMAIL_TEXT, APPSETTING_RESET_EMAIL_HTML, APPSETTING_RESET_EMAIL_SUBJECT, APPSETTING_RESET_EMAIL_TEXT, APPSETTING_RESET_EMAIL_HTML the subject, text and html contents of Create users and Reset passwords messages respectively. User's Name and Password, are included using with the %s notation.

For an Azure web app, the environment variables, can be defined, through the Azure management portal, without the APPSETTING and CUSTOMCONNSTR prefixes, as Azure's Web apps. Application Settings and Connection Strings variables.

Please note that the certificate of the APPSETTING_API_HOST must be set up in PHP configuration files, in order to supress any error messages from PHP's curl. For information on how to add certificates to PHP Azure installations see this article.

You can now access the page in order to create users, send verification emails, and reset passwords. To access the service simpley create an application/json, HTTP POST call to https://www.example.com/userMgtAdapter.php, with this json body:

{
    "token": "YourClientFacingSecret",
    "action": "create",
    "username": "usersJidNode",
    "email":"usersemail@example.com",
    "name":"Joe Do"
}

or

{
    "token": "YourClientFacingSecret",
    "action": "reset_pass",
    "username": "usersJidNode",
    "email":"usersemail@example.com",
    "name":"Joe Do"
}

The reset_pass action also can update the user information. Upon succesful execution:

  1. HTTP code 200 is returned
  2. An email is sent to the user's email containing the temporary password. This must be forced to change, by the end user application.

 

Points of Interest

 

The SendGrid email service API is used in the article, using this function:

/*
 Send email with the following self explaining parametersw
*/
function senduserEmail ($to,$emailWrapper)    {
    if (empty($emailWrapper->ServiceApiSecret))  {
         returnErrorCode(503,"Email Service API Secret not initialized correctly");
         printf("Email Service API Secret not initialized correctly emailServiceApiSecret = $emailWrapper->ServiceApiSecret");
         printf(" userJidNode= $userJidNode userEmail  = $email password = $password sharedToken = $sharedToken serviceAction = $serviceAction userName = $userName");
         return;
     }
     $sendgrid = new SendGrid($emailWrapper->ServiceApiSecret);
     //Create a new SendGrid userEmail object and add your message details.
     $email = new SendGrid\Email();
     $email
         ->addTo($to)
         ->setFrom($emailWrapper->from)
         ->setSubject($emailWrapper->subject)
         ->setText($emailWrapper->text)
         ->setHtml($emailWrapper->html)
     ;
     $sendgrid->send($email);
}

As already mentioned the HTTP code 200 is returned, if the requested operation has succeed, and no exception has occured. If security tokens, client facing or REST API facing are not provided, or if they are not correct an 4XX or 5XX error is returned, depending on the error condition, using this function:

 /*
     Return an HTTP Error Code, indicating an operation failure
  */
 function returnErrorCode ($httpStatusCode, $httpStatusMsg)    {
     $phpSapiName    = substr(php_sapi_Name(), 0, 3);
     if ($phpSapiName == 'cgi' || $phpSapiName == 'fpm') {
         header('Status: '.$httpStatusCode.' '.$httpStatusMsg);
     } else {
         $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
         header($protocol.' '.$httpStatusCode.' '.$httpStatusMsg);
     }
}

Conclusions

This article describes an adapter like pattern, that can be used for any service, that wishes to adapt an interface that must not be shared over the internet, third party applications, or  end user clients.

An example for the popular Openfire XMPP server is provided in PHP, but the same pattern can be applied for any XMPP server providing an administrative REST API.

History

First version of this article.

License

This article, along with any associated source code and files, is licensed under The Mozilla Public License 1.1 (MPL 1.1)