Just a second...

DEPRECATED: Authorization handlers

An authorization handler can control authorization and permissions for clients and users.

Role-based authorization

Attention: The new role-based security model has superseded authorization handlers. Role-based security enables you to more simply manage permissions and users. We recommend you use role-based authorization instead of authorization handlers. For more information, see Role-based authorization.

An authorization handler is a user-written Java™ class that must implement the AuthorisationHandler interface in the .

Such a handler can be used to restrict access of clients according to any criteria that is appropriate. One capability within Diffusion is for a client to be able to specify Credentials when they connect that can be checked by the authorization handler.

The handler can either be specified in etc/Server.xml in which case it is loaded when the server starts or can be set programmatically within a publisher using the Publishers.setAuthorisationHandler method.

There can only be one handler and it is system wide across all publishers, although you can have authorization at the publisher level.

If an authorization handler is not specified, credentials sent by a client are assumed to be valid. A publisher has access to the credentials to perform finer-grained authorization, if required.

The authorization handler interface has the following methods:

Table 1. Authorization handler methods
DEPRECATED: canConnect(Client) This method is called to establish whether the client can connect and is called before any client validation policy is called.
canSubscribe(Client, Topic) This method is called when a client subscribes to a topic. If topic information is sent with the connection, this method is called after the canConnect method.
Note: This is called for every topic being subscribed to, even if subscribed as a result of a topic selector being specified. However (by default), if a topic is rejected by this method, it is not called again for any children (or descendants) of the topic.
canSubscribe(Client, TopicSelector) This method is called when a client attempts to subscribe to a topic selector pattern (as opposed to a simple topic name). If topic information is sent with the connection, this method is called after the canConnect method.
canFetch(Client, Topic) This method is called when a client sends a fetch request to obtain the current state of a topic.
Note: This is called for every topic being fetched, even if fetched as a result of a topic selector being specified. However (by default), if a topic is rejected by this method, it is not be called again for any children (or descendants) of the topic.
canFetch(Client, TopicSelector) This method is called when a client attempts to fetch topics using a topic selector pattern (as opposed to a simple topic name).
canWrite(Client, Topic) This method is called when a client sends a message on a given topic, if false is returned the message is ignored, and the publisher will not be notified of the message. When implementing this method, be aware that performance can be impacted if many clients send messages or if a few clients send large messages.
DEPRECATED: credentialsSupplied(Client, Credentials) This method is called when a client submits credentials after connection. It can be used to validate the credentials and must return true if the credentials are OK. If this returns false, a Credentials Rejected message are sent back to the client.

Authentication

Note: The use of authorization handlers for authentication is deprecated. We recommend that you re-implement your authentication logic using authentication handlers. For more information, see User-written authentication handlers.

When a client connects to Diffusion it has the option of supplying user credentials. These credentials are basically tokens called username and password. These tokens can be used for any purpose. When canConnect is called, you can get the credentials from the Client object.

An example of this is:

    public boolean canConnect(Client client) {
	Credentials creds = client.getCredentials();

	// No creds supplied, so reject the connection
	if (creds == null) {
	    return false;
	}
	
	String username = creds.getUsername().toLowerCase();

If the credentials are null, none were supplied, which is different from empty credentials. If you set the username as an empty string (that is, an anonymous user) the password is not stored and you cannot retrieve it with getCredentials.

Clients can connect without credentials and submit them later or replace the credentials at any time whilst connected. The authorization handler is notified when new credentials are submitted and can choose to set the new credentials on the client.

The Credentials class has username and password attributes, but also allows for an attachment. It is here that a user normally sets any security object required. Returning true will allow the user to connect, returning false will result in the client connection being refused.

Subscription authorization

Subscription authorization is the allowing of a client to subscribe to a topic. In this case the canSubscribe is called. Returning true here allows the publisher to have any topic loaders and subscription methods called. Returning false will not notify the client that the subscription was invalid.

public boolean canSubscribe(Client client, Topic topic) {

    // Everyone has access to the top level topic
    if (topic.getName().equals(CHAT_TOPIC)) {
        return true;
    }

    User user = (User) client.getCredentials().attachment();

    return user.isAllowedRoom(topic.getNodeName());
}

Authorization handler

Authorization at the publisher level can also be achieved. This is required if there are many publishers running within the same Diffusion Server and they have different security settings. The following code example works if the publishers all implement AuthorisationHandler

public boolean canSubscribe(Client client, Topic topic) {

    AuthorisationHandler handler = 
            (AuthorisationHandler)Publishers.getPublisherForTopic(topic);

    // Call the publisher in question
    return handler.canSubscribe(client, topic);
}

Permissions

The permissions process governs whether a client is able to send messages to a publisher, or in other words, is the topic read only. This is handled by the canWrite method. Again a good pattern might be to look at the credentials attachment object to see if this is permissible.

public boolean canWrite(Client client, Topic topic) {
	User user = (User) client.getClientCredentials().attachment();
	return user.canWriteMessages(topic);
}