Authorizer configuration and function


A local deployment will typically have a single Authorizer node instance, which is declared to handle all incoming synchronous messages (queries). While processing a query, an internal node may have to make a subsequent call to another system, and will make use of the Authorizer to bridge the gap.

Query stack example:

If a node needs to send an asynchronous message out of the system, then it may do that directly (and anyone in the world can subscribe to the node directly), or it may want to restrict access. Without using features specific to the messaging system, you can't prevent someone subscribing to the node, the SAND model states that you instead publish the message so that only the intended recipients can properly receive it.

In the absolute simplest case, the node doing the sending will create an AuthWrapper for the message. So only subscribers that are able to decode the AuthWrapper will be able to read it. Typically the wrapping function would be delegated to a cooperative outgoing adaptor node.

Simple outgoing send example:

If the adaptor is on another machine with an untrusted communication channel, then an authorizer pair will need to bridge the gap.

Remote outgoing adaptor send:

How the AuthWrapper is created from the outgoing message is application specific. It could be as simple as using one username for all output, a few usernames representing logical groups, or individual usernames for each recipient. You could have a single outgoing adaptor node, or multiple outgoing adaptor nodes (such as one dedicated node for each user group, or a pool of general use nodes with some form of load balancing).

Tracking synchronous call threads:

For the Authorizer to be able to correctly construct an AuthWrapper for an intermediate synchronous call outside the local deployment, it needs to be able to associate that call with the appropriate originating request. This is necessary so that the original username/password information is preserved through an unlimited number of system hops.

Preservation of this thread is the responsibility of the messaging implementation. In the example above, an ID of 127 was associated with the synchronous request thread. This is for conceptual purposes, there is no actual ID field associated with a SandMessage. For full details on how this concept is actually implemented, refer to the mesaging system implementation. For illustration purposes of how this might be done, consider the following description:

When a node makes a synchronous request, the messaging implementation first checks to see if the node being called is local within the same process space. If it is, then the appropriate receive method in the target node is simply called directly. Local calls are trusted and do not explicitely require username/password information.

While direct messaging has many advantages, calls outside of the local process space require username/password information to construct an AuthWrapper message. This construction and initial query is typically the job of an adaptor node (such as HTTPAdaptor). Once sent, the message is received by an Authorizer, which

  1. stores the original AuthWrapper message using the current Thread as the key
  2. unpacks the content message and queries the appropriate processing node with it

If the local processing node needs to make a subsequent query outside the system to complete the request, that query will go out via the Authorizer. To find the username/password information needed to construct a new AuthWrapper, the Authorizer looks up the originating AuthWrapper via the current Thread.

If no originating AuthWrapper is found, then this query is starting from inside the local deployment. Some authorizers might support this, but most applications will probably make use of dedicated adaptor nodes to keep the functions cleanly separated.