Thursday, October 30, 2014

Authentication & Authorization With Lightstreamer

This short article will guide you through authentication and authorization in Lightstreamer and will introduce a live example with full source code.


Most, if not all, Lightstreamer applications will, at some point, require some sort of authentication mechanism to validate their users. Moreover, there usually is an authentication mechanism already in place when Lightstreamer is introduced in the system.

So, let's see how to introduce Lightstreamer in an environment where Authentication is already handled by a Web/Application server.

The MetadataProvider interface of Lightstreamer delegates the authentication to custom code, hence any scenario is totally feasible no matter how the current authentication cycle currently is. Anyway, in this article, we will focus on a rather common pattern where, upon authentication, the Web Server returns a token to the client (e.g.: through a cookie or through an ajax response) and the client uses that token every time it has to request data requiring an authenticated user to the same server. All in all, the user/password pair is only used once (well, the token will expire sooner or later, that's pretty obvious).

Instead of authenticating again the user, using the password within the Metadata Adapter, the suggested approach is to send the token received from the Web Server to Lightstreamer Server; in turn. the Metadata Adapter will validate the received token against the common back-end.

So, first thing, from the client, we grab user and password and we send them to the existing Web Server. In case of success we will have our token.

Then we can put the token in our LightstreamerClient instance, and connect to the Lightstreamer server:

On the other side, Lightstreamer will receive the request and will call the notifyUser method on the MetadataProvider implementation in use. The notifyUser will validate the user/token against the back-end and, if valid, will not throw any exception. On the contrary, an AccessException will be thrown to notify the server of the failed authentication. In the below code, the query to the external back-end is wrapped inside the isValidToken method:

If the connection is refused the client listeners will receive an onServerError call

Otherwise, the connection will start.

Authentication is now complete.


Not all users are created equal though. Some will have access to certain items that others cannot see. The MetadataProvider also provides hooks where these kind of fine-grained authorization can be implemented and enforced.

The MetadataProvider must first declare it wants to verify each and every subscription:

then, when the client subscribes to a list of items,

the MetadataProvider will receive a call to notifyNewTables. Each TableInfo instance represents a subscription, and each subscription might contain several items. The item names in the TableInfo instance are in the form of a single string as it is sent by the client. We delegate to the  getItems the explosion of the list.
As with user's authentication, in this example, the authorization policy is wrapped in a single method, namely canUserSeeItems. If the method fails to authorize the user against the items, a CreditsException has to be thrown to prevent the subscription from being fullfilled.

Again, a listener on the Subscription is notified if the subscription is refused or did start, permitting the client code to act accordingly:

This is just an overview of the basic authentication and authorization workflow. As you can see, you can hook your own system to Lightstreamer Metadata Adapter to perform these activities with your own back-end.


If you want  to dig a little more on the topic, and start coding yourself, we suggest to explore the following projects:
These projects still fake the requests to the back-end with static collections, but contain many useful comments and a simple implementation of an authorization caching mechanism.

The live result can be seen here:

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.