[Download] | [Documentation Home] | [Release Note]

Dynamic User Authentication

Introduction

This functionality allows users to authenticate database users dynamically for each data service call. This is done using a mapping between the Carbon users and the database users. This mappings can be given as a static mapping inside the data service configuration itself, or an Java class implementation can be given which implements the interface org.wso2.carbon.dataservices.core.auth.DynamicUserAuthenticator to provide the mapping at runtime.

Static Configuration

The static configuration can be given in the data source configuration section of the data service. Below contains a sample configuration snippet on how this is done.

   
   <data name="RDBMSSample" serviceGroup="RDBMS">                           
   <config id="default">                                                      
      <property name="driverClassName">org.h2.Driver</property>                                                      
      <property name="url">jdbc:h2:file:./samples/database/DATA_SERV_SAMP</property>                                                      
      <property name="username">wso2ds</property>                                                      
      <property name="password">wso2ds</property>                                             
      <property name="dynamicUserAuthMapping">                                                                        
         <configuration>                                                                                               
            <entry request="admin">                                                                                                                      
               <username>wso2ds</username>                                                                                                                      
               <password>wso2ds</password>                                                                                               
            </entry>                                                
            <entry request="user1">                                                                                                                      
               <username>dbuser1</username>                                                                                                                      
               <password>dbpass1</password>                                                                                               
            </entry>            
            <entry request="*">                                                                                                                      
               <username>guest</username>                                                                                                                      
               <password>guest</password>                                                                                               
            </entry>                                                                        
         </configuration>                                                
      </property>                            
   </config>  
   ....
   

In the above configuration, it maps the two Carbon users to specific database credentials and all the rest of the users to a different username/password pair. In the XML configuration of "dynamicUserAuthMapping" property, at the location "/configuration/entry/@request", that attribute represents the incoming Carbon user, and the following "username" and "password" elements represents the mapped database credentials.

For dynamic user authentication to work, security should be enabled in the data service with a scenario such as UsernameToken for user authentication. If user authentication is not available when a "dynamicUserAuthMapping" section is there, it will, by default map to the request="*" scenario.

Dynamic User Auth Mapping
Figure 01: Dynamic User Auth Mapping

Figure 01 shows the UI at the data sources page in configuring dynamic user mappings, where for each entry, the Carbon user and the target database user / password can be mapped.

Runtime Request User Mapping Configuration

In this mode, rather than providing the data source configuration property "dynamicUserAuthMapping", we should provide the property "dynamicUserAuthClass", with the value containing the fully qualified class name of a Java class which implements the interface org.wso2.carbon.dataservices.core.auth.DynamicUserAuthenticator. The interface is as follows:

    public interface DynamicUserAuthenticator {

        /**
        * This method is used to lookup a username/password pair given a source username.
        * @param user The source username
        * @return A two element String array containing the username and password respectively
        * @throws DataServiceFault
        */
        String[] lookupCredentials(String user) throws DataServiceFault;

    }
  

The following shows a sample implementation of a dynamic user authenticator class:

    package samples;

    import org.wso2.carbon.dataservices.core.DataServiceFault;
    import org.wso2.carbon.dataservices.core.auth.DynamicUserAuthenticator;

    public class MyDynAuthClass implements DynamicUserAuthenticator {

        @Override
        public String[] lookupCredentials(String user) throws DataServiceFault {
                if ("admin".equals(user)) {
                   return new String[] {"wso2ds", "wso2ds"};
                } else if ("user1".equals(user)) {
                   return new String[] {"dbuser1", "dbpass1"};
                } else if ("user2".equals(user)) {
                   return new String[] {"dbuser2", "dbpass2"};
                } else {
                   throw new DataServiceFault("The user '" + user + 
                           "' not supported in invoking the target data service");
                }
        }

    }
  

The "lookupCredentials" method takes in the request user and should return the database username/password in a String array respectively.

The dbs file configuration format is as follows:
   
   <data name="RDBMSSample" serviceGroup="RDBMS">                           
   <config id="default">                                                      
      <property name="driverClassName">org.h2.Driver</property>                                                      
      <property name="url">jdbc:h2:file:./samples/database/DATA_SERV_SAMP</property>                                                      
      <property name="username">wso2ds</property>                                                      
      <property name="password">wso2ds</property>                                             
      <property name="dynamicUserAuthClass">samples.MyDynAuthClass</property>                                                                        
         
   ....
   

Dynamic User Auth Class
Figure 02: Dynamic User Auth Class

Figure 02 shows that the dynamic user auth class can be given in the shown field

The Dynamic User Lookup Order of Precedence

In a single data source configuration, both the static mapping and the runtime configuration given by the Java class can be available. In that type of a situation, the higher precedence goes to the static mapping in initially looking up the credentials, and it will ignore the "*" request setting in the first pass. If it cannot find a request user / database credentials mapping, we will use the secondary runtime Java class implementation to look up the user, if that also fails, it will return again for the primary static mapping and process the "*" request mapping. If that also fails, the data service request will return an error.

The Use of External Data Sources

When using non-inline data sources, i.e. Carbon data sources, JNDI data sources etc.., the data sources must be created in a way that its connections can be created for specific users. Specifically, in Carbon data sources, the setting "alternateUsernameAllowed" must be enabled for dynamic user authentication to function.