Overview

When there are special device-RM authentication requirements, that are not met in the ready-to-use authentication plugins, then the user can plug his own authentication plugin.

As it has already been explained the RM provides beneficial pluggable hook mechanism for authenticating connections coming from an OSGi device.

  • On the RM side the communication hook mechanism is achieved by adding a bundle implementing com.prosyst.mprm.backend.ms.gm.CustomAuthenticationPluginEx or com.prosyst.mprm.backend.ms.gm.CustomAuthenticationPlugin interface. The implementation should be registered as an OSGi Service in the OSGi Service Registry. The acceptConnection(GatewayConnectionContext connectionContext, byte[] credentials) and respectively the acceptConnection(GatewayConnectionContext connectionContext) method is invoked by RM every time a gateway is connecting. This method implementation allows or denies gateway connection according to the authentication policy.

Only one of the authentication plugins is used. The CustomAuthenticationPlugin has priority over the CustomAuthenticationPluginEx and if both plugins are registered, the CustomAuthenticationPlugin will be used. 

  • On the gateway side the communication hook mechanism is a bundle implementing com.prosyst.mprm.gateway.authentication.PRMAuthentication interface. The implementation should be registered as an OSGi Service in the OSGi Service Registry. The getCredentials() method should return the credentials to be used for verification on the RM.

It depends on the customer needs which interface will be implemented and registered. If the customer needs to verify some custom data sent from the device, then the CustomAuthenticationPluginEx should be implemented, otherwise, the CustomAuthenticationPlugin should be used.

Server Side Custom Authentication Plugin Examples

Implementing CustomAuthenticationPluginEx


Below is the code snippet of an example of how to implement the CustomAuthenticationPluginEx interface and register it in the OSGi registry. . 

...
public class CustomAuthenticationPluginExImpl implements BundleActivator, CustomAuthenticationPluginEx {
 
private ServiceRegistration reg;
public void start(BundleContext bc) throws Exception {
reg = bc.registerService(CustomAuthenticationPluginEx.class.getName(), this, null);
}
public void stop(BundleContext bc) throws Exception {
if (reg != null) {
reg.unregister();
reg = null;
}
}
 
public byte[] acceptConnection(GatewayConnectionContext connectionContext, byte[] credentials) throws ManagementException {
/* Throw an exception if the connection should be refused, otherwise return any user specific data
* needed for authentication on the device if the authentication is bidirectional or null otherwise
*/
return null;
}
}



Implementing CustomAuthenticationPlugin

Another way to plug a custom authentication plugin is CustomAuthenticationPluginImpl interface.

...
public class CustomAuthenticationPluginImpl implements BundleActivator, CustomAuthenticationPlugin {
 
private ServiceRegistration reg;
public void start(BundleContext bc) throws Exception {
reg = bc.registerService(CustomAuthenticationPluginEx.class.getName(), this, null);
}
public void stop(BundleContext bc) throws Exception {
if (reg != null) {
reg.unregister();
reg = null;
}
}
 
public void acceptConnection(GatewayConnectionContext connectionContext) throws ManagementException {
/* Allow or refuse the device connection according to the custom policy. Throw an exception if the connection should be refused */
}


Client Side Custom Authentication Plugin Examples


Below is the code snippet of an example of how to implement the PRMAuthentication interface and register it in the OSGi service registry: 

...
public class PRMAuthenticationImpl implements BundleActivator, PRMAuthentication {
 
private ServiceRegistration reg;
public void start(BundleContext bc) throws Exception {
reg = bc.registerService(PRMAuthentication.class.getName(), this, null);
}
public void stop(BundleContext bc) throws Exception {
if (reg != null) {
reg.unregister();
reg = null;
}
}
public byte[] getCredentials() {
/* Return any user specific information which will be needed to be verified on the RM */
return null;
}
 
public boolean verify(byte[] credentials) {
/* Verify here the credentials received from the RM, if the authentication is bidirectional
* This method returns true if it accepts the connection, otherwise false.
*/
return true;
}

For the special case when the basic authentication verifier is activated (see Basic Authentication Verifier), a client side implementation, providing the username and password to be verified, is needed. Below is an example of how it should look like. 

...
public class BasicAuthenticationProvider implements BundleActivator, PRMAuthentication {
 
private ServiceRegistration reg;
public void start(BundleContext bc) throws Exception {
reg = bc.registerService(PRMAuthentication.class.getName(), this, null);
}
public void stop(BundleContext bc) throws Exception {
if (reg != null) {
reg.unregister();
reg = null;
}
}
public byte[] getCredentials() {
try {
String username = null;
String password = null;
/* Initialize here the username and password to be verified on the RM */
/* Return the username and password to the RM */
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(byteOut);
dataOut.writeUTF(username);
dataOut.writeUTF(password);
return byteOut.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
 
public boolean verify(byte[] credentials) {
/* Verify here the credentials received from the RM, if the authentication is bidirectional
* This method returns true if it accepts the connection, otherwise false.
*/
return true;
}
 
}