As we have seen in a previous article we developed real-time capability in Tuleap for Kanban and Test Management modules, using WebSocket and Node.js technologies. This post focuses on another great challenge for real-time tools: how to really make communication secure, how to control user identity, how to manage permissions and access control.

The challenge of data security and access control in real-time

A strong responsibility of real-time tools is to ensure security when broadcasting messages to connected users. Without this in Tuleap, any client could subscribe to the server, listen to the events and receive data initially protected.

Challenge: How to ensure the sending of information

The information exchanged relates to Tuleap Issue Tracking plugin. It provides fine-grained access control and permissions capabilities on artifacts. It is possible to specify which user groups have rights to read artifacts and make changes. For the broadcasting message, permissions have to be checked for each connected user in order to send the information securely.

Secure Broadcast Communications

The server needs to know to which groups the subscribed users belong to and the permissions there are on each broadcasted message. To avoid too numerous number of communication between all the entities, that is the Web client that is responsible of sending all of its groups, as soon as it subscribes to Tuleap real-time. In this configuration, the Web client requests the data from the Tuleap server and sends it to the Tuleap real-time server.

Several issues arise when receiving this data:

Does the Web client modify the message?

Does data come from Tuleap?

Therefore, the Tuleap real-time server must verify the integrity and the authentication of data it receives. To carry out this checking, we used the Json Web Tokens, standardized by RFC 7519.

What are JSON Web Tokens

JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between several parties. Tokens are represented by an encoded base64 string with several parts separated by dots. They are stateless so they aren’t stored in database. They can be sent through an URL, in the POST body, or in the HTTP header. They can be signed or encrypted with a secret key or a public / private key pair using different algorithms (signature: HMAC, RSA, encryption: RSA, Elgamal).

We talk about JSON Web Signature (RFC 7515) when the token is signed and about JSON Web Encryption (RFC 7516) when it is encrypted.

In this article, we will only see the JSON Web Signature that we used in our case. The signed token is made of :

a header : JSON object containing the information of the used algorithm and the type of the token,

a payload : JSON object containing claims that are key / value pairs on an entity and metadata,

a signature, using payload as the concatenation of the encoded header and payload.

To sign our token with a secret key, shared between two servers, Tuleap calculates the value of the signature from its original data and sends it into the signature part of the JSON Web Signature. Tuleap real-time server calculates in turn a signature from the data received and verifies that the computed value matches the one which has been sent.

Any changes made to the data or to the signature will be pinpoint as the secret key is used in the calculation. Thus the Tuleap real-time server can know if the sender is the Tuleap one and if the content sent has not been altered.

Data sent securely

Understanding Tuleap communications with JSON Web Tokens (JWT)

The exchanges between the different entities, including the JSON Web Tokens, are as follows:

A web client wants to subscribe for real-time. It first asks for a subscription token to Tuleap; Tuleap sends the data in the form of a signed token with the secret key to the Web client; The Web client sends it to the Tuleap real-time server; Tuleap real-time checks the signatures. If the two signatures are equivalent then it stores the user in the corresponding room (the Web client can receive the data in real-time). Otherwise the user is disconnected with the message “unauthorized”. When the Tuleap server sends a message to the Tuleap real-time server, it compares the associated permissions to the message with the groups of each connected user in the same “room” of the sender. If the user is allowed, he receives the message, otherwise nothing is sent.

Sequence diagram Subscription with user rights exchanged and card creation example

Technically on Tuleap real-time server

Tuleap real-time server has a custom module “JWT” which uses the library Node.js “jsonwebtoken”. This module contains the secret key shared with the Tuleap server and has several methods for decoding the token :

by checking the signature,

by checking its expiration date,

and its structure.

this.privateKey = private_key; this.isDateExpired = function(expired_date) { return expired_date <= Date.now(); }; this.isTokenValid = function(decoded) { return _.has(decoded, 'exp') && _.has(decoded, 'data.user_id') && _.has(decoded, 'data.user_rights'); }; this.decodeToken = function(token, callback) { var data; try { data = jwt.verify(token, this.privateKey); } catch(err) { callback(err); } return data; };

“JWT” module on Tuleap real-time

In addition, the real-time server has another module, named “rights”, to check rights before broadcast Tuleap messages. We compare the permissions on the message to the groups of each connected user (sent at the subscription in the JSON Web Token), who are in the same room that the sender, calling the method “userCanReceiveData”:

self.userCanReceiveData = function(user_id, user_rights) { var data_submitter_id = user_rights.submitter_id; return (hasUserRights(self.ugroups_collection[user_id], user_rights)) || (data_submitter_id === user_id && hasUserRightsAsSubmitter( self.ugroups_collection[user_id], user_rights ) ); }; function hasUserRights(u_group, user_rights) { var find_right_artifact = false; var find_right_tracker = hasUserRightsExist(u_group, user_rights.tracker); if (user_rights.artifact.length > 0) { find_right_artifact = hasUserRightsExist(u_group, user_rights.artifact); } else { find_right_artifact = true; } return find_right_tracker && find_right_artifact; } function hasUserRightsAsSubmitter(u_group, user_rights) { var find_right_submitter = false; if (user_rights.submitter_can_view) { find_right_submitter = hasUserRightsExist( u_group, user_rights.submitter_only ); } return find_right_submitter; } function hasUserRightsExist(u_group, user_rights) { return _.some(user_rights, function(right) { return _.contains(u_group, right); }); }

“Rights” module on Tuleap real-time server

Security challenge achieved. Thank you JWT

Using JWT, our new server can have all integrated and authenticated user groups as soon as a user subscribes, without asking anything to the Tuleap server. Then, when data have to be broadcasted, it can check the permissions of each recipient in a secure manner. Therefore, it complies with Tuleap’s policy ; it disseminates data only to authorized persons.