Hi All,
WSO2 MB currently only supports authentication. The current implementation
is an extensible approach, where we can plug custom authenticators. However
it does not support authorization and this creates a security concern where
any one who is authenticated can publish or subscribe to any topics.

This is a concern for IoT use-cases, where if an application needs to
publish data(eg: control operation) to a device then we require an
authorization layer to validate who can send commands to that particular
device. Hence, we have extended the current model in WSO2 MB to support
authorization for MQTT.

Below is the flow of the architecture and the common idea on how
authentication and authorization is supported.
When a client wants to publish/subscribe then they have to follow two steps.

   - Step 1 : Client connects to the Broker
   - Step 2 : Client publish/subscribe to topics.

In the above steps authentication happens in Step 1 and this session will
be maintained for Step 2. However if we think about authorization then
there should be two levels to consider.

   - Level 1 : Is the client authorised to connect to the broker
   (Authorization in Step 1)
   - Level 2 : Is the client authorised to publish or subscribe to a
   specific topic (Authorization in Step 2)

Now lets consider how we can solve authorization in both the levels. (Here
I have taken OAuth based approach to explain the flow)

*Level 1:* eg : Scope based authorization


   - Step 1:  client sends a token
   - Step 2:  validate the token
   - Step 3 : (if authentication is successful) Check whether the scope
   related to token matches with the required scope to connect to the client.

      <authenticator class=
"org.wso2.carbon.andes.authentication.andes.OAuth2BasedMQTTAuthenticator">
          <property name="hostURL">
https://localhost:9443/services/OAuth2TokenValidationService</property>
          <property name="username">admin</property>
          <property name="password">admin</property>
          <!--<authenticate the user only if below scopes are related to
the token.
          This value can be empty if we wanted skip the authorization for
connection
          Multiple scopes can mentioned by having a space delimiter>-->
          *<property name="scopes"></property>*
           <property name="maxConnectionsPerHost">10</property>
           <property name="maxTotalConnections">150</property>
       </authenticator>

Similarly for Basic Authentication it will follow a role based
authorization. In the implementation aspect in the MB this needs to done
within the authenticator extension.

*Level 2:*
In MQTT specification it has been mentioned that:
*"An implementation may restrict access to Server resources based on
information provided by the Client such as User Name, Client Identifier,
the hostname/IP address of the Client, or the outcome of authentication
mechanisms."*

In here we will be following the second approach where outcome of
authentication will be passed to authorization.

In Level 2 the required steps to authrozie will be.

*Publisher flow*,
After the client gets connected then it will publish the message to a
particular topic.
In here we have the information related to the client which is stored and
retrieved after authentication(this could be scopes that are related to the
token or the username) and the topic that the client needs to publish.

*Subscriber flow*
In subscriber flow the client has the similar information as publisher that
are retrieved from authentication. However in the subscribe use case it can
subscribe to multiple topics.

For both instances if the authorization fails then the client will be
disconnected from the broker.

To achieve this we have created an interface that can be used to plug any
authorization logic. This can be simple configured in broker.xml by adding
below both tags.
                     <!--
                       Instructs the MQTT server whether clients should be
authorized before either publishing or subscribing
                       Possible values:
                        NOT_REQUIRED: This is the default value. MQTT
clients will skip the authorization check
                        REQUIRED: Clients will authorized before
publishing/subscribing. this will execute the class given in authorzier
                        Note: authentication should be REQUIRED for
authorization to be REQUIRED.
                   -->
                    <authorization>NOT_REQUIRED</authorization>

                    <!--Class name of the authorizer to use. class should
                        inherit from
org.dna.mqtt.moquette.server.IAutherizer
                        Note: default implementation authorizes against
carbon permission with the topic.
                    -->
                    <authorizer
class="org.wso2.carbon.andes.authorization.andes.CarbonPermissionBasedMQTTAuthorizer"/>

The reason for having pluggable authorization is because MQTT-topics are
designed specific to use cases and these topic could be dynamic. Therefore
it is difficult to bring this into a common template. One such example is
that in an IoT use case:

User sends a specific command to all his raspberry pi devices. User
publishes to the topic:*iot/username/raspberrypi/#*
Device will be subscribed to the topic:
*iot/username/raspberrypi/{deviceId}*.

If there are multiple users and device id then it will be mapped to a
template such as iot/{username}/raspberrypi/{deviceId}. In this case the
authorization should be on whether the user has the access to particular
device(extract the username and device id from topic). This needs custom
implementation and this is supported through the interface.

flow of authentication and authorzation is depicted in below image

​

*Furthermore I have a done basic authorization implementaion based on
Carbon Permission model. Where we can map the topic directly to permission
hierarchy. This will only be practical for static topics. *
e.g.:
If a client wants to publish to wso2/clubs or wso2/teamgroups then the
client requires the minimum permission for :
/permission/mqtt/topic/wso2/clubs and
/permission/mqtt/topic/wso2/teamgroups respectively with the action
'publish'. In here "/permission/mqtt/topic" is a prefix for all topics to
map into one hierarchy. Further if the client has permission for
/permission/mqtt/topic/wso2 with the 'publish' action then the client can
publish to both  wso2/clubs or wso2/teamgroups topics. Similarly subscriber
requires the permission with the action 'subscribe'.
The source code for this implementation is available in [2][3].

[1] http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
[2] https://github.com/wso2/andes/pull/517
[3] https://github.com/wso2/carbon-business-messaging/pull/256
*Ayyoob Hamza*
*Software Engineer*
WSO2 Inc.; http://wso2.com
email: ayy...@wso2.com cell: +94 77 1681010 <%2B94%2077%207779495>
_______________________________________________
Architecture mailing list
Architecture@wso2.org
https://mail.wso2.org/cgi-bin/mailman/listinfo/architecture

Reply via email to