How to Implement JDBC Authentication and Authorization in Mule 4 Using Spring Security

In Mule, we use Spring Security to achieve basic authentication and authorization functionality. So let's see how to achieve this with Spring Security and Mule 4.

First, create a simple Mule project.

Creating a Mule project

Creating a Mule project



Add an HTTP listener, transform the message, and run it to make sure everything is working as expected before we start working on the security. It is always good to take things step-by-step and test them after each step.  

Running the project

Running the project



I used Postman to test the flow. This is a simple flow and there's nothing special about it. The HTTP connector and transform message are working as expected, so let's move on.

Now let's implement a basic authorization Spring Security where the user name and password are defined with in the application. 

To implement Spring Security we need to define a Spring beans file with an authentication manager, for which we need to add Spring modules into our pom file first. I'm going to add the following dependencies to my pom file.

Java
 




x
20


1
<dependency>
2
   <groupId>org.springframework.security</groupId>
3
   <artifactId>spring-security-core</artifactId>
4
   <version>4.1.5.RELEASE</version>
5
  </dependency>
6
  <dependency>
7
   <groupId>org.springframework.security</groupId>
8
   <artifactId>spring-security-config</artifactId>
9
   <version>4.1.5.RELEASE</version>
10
  </dependency>
11
  <dependency>
12
   <groupId>org.springframework</groupId>
13
   <artifactId>spring-context</artifactId>
14
   <version>4.1.5.RELEASE</version>
15
  </dependency>
16
  <dependency>
17
   <groupId>org.springframework</groupId>
18
   <artifactId>spring-beans</artifactId>
19
   <version>4.1.5.RELEASE</version>
20
  </dependency>
21
        <dependency>
22
   <groupId>org.mule.modules</groupId>
23
   <artifactId>mule-spring-module</artifactId>
24
   <version>1.3.2</version>
25
   <classifier>mule-plugin</classifier>
26
  </dependency>
27
  <dependency>
28
   <groupId>org.springframework</groupId>
29
   <artifactId>spring-core</artifactId>
30
   <version>4.1.5.RELEASE</version>
31
  </dependency>



Important Note: I have used the Spring version 4.1.5.RELEASE for all Spring Security-related dependencies. Spring Security is not working with later versions, I have tried with most of the 5.1 releases and security did not work as expected. After a lot of trial and error, I came to a conclusion this 4.1.5 release is stable and Security is working as expected in Mule 4. So you have to use the same version. If anyone can get it working with newer versions please update.

All the dependencies mentioned above should be added to your pom for Spring Security to work.

Now create a Bpring beans file and define the authentication manager as shown below: 

Spring beans file

Spring beans file



spring-beans file:

Java
 




xxxxxxxxxx
1
24


 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<beans xmlns="http://www.springframework.org/schema/beans"
3
  xmlns:context="http://www.springframework.org/schema/context"
4
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
  xmlns:ss="http://www.springframework.org/schema/security"
6
  xsi:schemaLocation="http://www.springframework.org/schema/beans
7
    http://www.springframework.org/schema/beans/spring-beans.xsd
8
 
          
9
    http://www.springframework.org/schema/context
10
    http://www.springframework.org/schema/context/spring-context.xsd
11
    http://www.springframework.org/schema/security
12
    http://www.springframework.org/schema/security/spring-security.xsd">
13
    
14
    
15
 <ss:authentication-manager alias="authenticationManager" id="authenticationManager">
16
  <ss:authentication-provider>
17
   <ss:user-service id="userService">
18
           <ss:user name="admin" password="admin" authorities="ROLE_ADMIN" /> 
19
           <ss:user name="harsha" password="welcome" authorities="ROLE_USER" />  
20
          </ss:user-service>
21
  </ss:authentication-provider>
22
 </ss:authentication-manager>
23
 
24
</beans>



Now that we added Spring beans and the authentication manager, let's add this to our Mule flow. To do that, add the following code in the Mule flow we have created earlier. 

Java
 




xxxxxxxxxx
1


1
<spring:config name="springConfig" files="spring-beans.xml"/>
2
       <spring:security-manager doc:name="Spring Security manager" doc:id="e5d7f618-823f-417d-a72b-b9c6bd81b291" >
3
        <spring:delegate-security-provider name="mule-provider" delegate-ref="authenticationManager" />
4
    </spring:security-manager>



Now our Mule flow can access the authentication manager defined in the Spring beans file. We are ready to use Spring Security.

Let's add an HTTP basic auth and Spring authorization filter between rgw HTTP listener and transform the message in the flow we created earlier. Also, we will allow only a user with the role "ROLE_ADMIN" to access our flow. After applying all the changes the flow looks something like this.

Mule flow after adding auth filter

Mule flow after adding auth filter


XML view of the Mule flow

Java
 




xxxxxxxxxx
1
48


1
<?xml version="1.0" encoding="UTF-8"?>
2
<mule
3
  xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
4
  xmlns:http="http://www.mulesoft.org/schema/mule/http"
5
  xmlns:db="http://www.mulesoft.org/schema/mule/db"
6
  xmlns:spring="http://www.mulesoft.org/schema/mule/spring"
7
  xmlns="http://www.mulesoft.org/schema/mule/core"
8
  xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
9
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
10
    http://www.springframework.org/schema/beans/spring-beans-current.xsd
11
    http://www.mulesoft.org/schema/mule/core
12
    http://www.mulesoft.org/schema/mule/core/current/mule.xsd
13
    http://www.mulesoft.org/schema/mule/spring
14
    http://www.mulesoft.org/schema/mule/spring/current/mule-spring.xsd
15
    http://www.mulesoft.org/schema/mule/db
16
    http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
17
    http://www.mulesoft.org/schema/mule/http
18
    http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
19
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd">
20
 
          
21
     <spring:config name="springConfig" files="spring-beans.xml"/>
22
 
23
    <spring:security-manager doc:name="Spring Security manager" doc:id="e5d7f618-823f-417d-a72b-b9c6bd81b291" >
24
  <spring:delegate-security-provider name="mule-provider" delegate-ref="authenticationManager" />
25
 </spring:security-manager>
26
 
27
 <http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="49d5ebce-1968-4e3a-a885-7b6e6b84d822" basePath="/api" >
28
  <http:listener-connection host="0.0.0.0" port="8081" />
29
 </http:listener-config>
30
 <flow name="jdbc-security-mule4Flow" doc:id="affb8bcd-a612-4524-b9d1-75c9abfa1f95" >
31
  <http:listener doc:name="Listener" doc:id="48eef432-96d9-4f7c-a09b-21b1e5191e2e" config-ref="HTTP_Listener_config" path="/securityTest"/> 
32
 
          
33
 
          
34
  <http:basic-security-filter doc:name="Basic security filter" doc:id="848ee679-9322-4df5-bcc6-fa613b662472" realm="mule"/>
35
  <spring:authorization-filter doc:id="afe1d779-2490-4331-bcd0-36ff9f252804" doc:name="" requiredAuthorities="ROLE_ADMIN"/>
36
  <ee:transform doc:name="Transform Message" doc:id="194edaf8-5864-4367-b9b2-486283cab341" >
37
   <ee:message >
38
    <ee:set-payload ><![CDATA[%dw 2.0
39
output application/json
40
---
41
{
42
 Message : "Hello World"
43
}]]></ee:set-payload>
44
   </ee:message>
45
  </ee:transform>
46
 </flow>
47
</mule>
48
 
          



Now let's run the flow and test it.

First, let's test it with the user admin. This user has the role "ROLE_ADMIN," so this user should be able to access our flow.

Testing with user admin

Testing with user admin


As expected, this user is able to access the flow successfully. Now let's test with user "harsha." This user has the role "ROLE_USER" so he should not be able to access the flow. Let's try:

Testing with user harsha

Testing with user harsha


As expected, we see an error. User authentication was successful but the user was unable to access flow as only a user with ROLE_ADMIN can access this flow.

Ok, now we have applied basic security and were able to verify security is working as expected. Now it's time to get to the most interesting part: applying JDBC authentication and authorization.

We have already done most of the work. Now we simply need to define two tables with user and user role details in oracle database and create an authentication manager which communicates to those tables to authenticate and authorize user. So let's get started.

First things first. Let's create two tables in database with name  USERS and  USER_ROLES. You can create tables with any name you like. It doesn't have to be what I used.

Users Table

Java
 




xxxxxxxxxx
1
18


1
 CREATE TABLE "HARSHA"."USERS" 
2
   ( "USER_ID" NUMBER NOT NULL ENABLE, 
3
 "USERNAME" VARCHAR2(50 BYTE), 
4
 "PASSWORD" VARCHAR2(50 BYTE), 
5
 "ENABLED" VARCHAR2(20 BYTE), 
6
  CONSTRAINT "USERS_PK" PRIMARY KEY ("USER_ID")
7
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
8
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
9
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
10
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
11
  TABLESPACE "USERS"  ENABLE
12
   ) SEGMENT CREATION IMMEDIATE 
13
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
14
 NOCOMPRESS LOGGING
15
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
16
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
17
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
18
  TABLESPACE "USERS" ;



User Roles

Java
 




xxxxxxxxxx
1
19


1
 
          
2
  CREATE TABLE "HARSHA"."USER_ROLES" 
3
   ( "USER_ROLE_ID" NUMBER NOT NULL ENABLE, 
4
 "USERNAME" VARCHAR2(50 BYTE), 
5
 "AUTHORITY" VARCHAR2(50 BYTE), 
6
  CONSTRAINT "USER_ROLES_PK" PRIMARY KEY ("USER_ROLE_ID")
7
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
8
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
9
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
10
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
11
  TABLESPACE "USERS"  ENABLE
12
   ) SEGMENT CREATION IMMEDIATE 
13
  PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
14
 NOCOMPRESS LOGGING
15
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
16
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
17
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
18
  TABLESPACE "USERS" ;
19
 
          



Now create a couple of users in the Users table and add roles to those users in the user roles table. See an example screenshot below.

Users table with two users

Users table with two users



Important Note: If you are using Oracle DB, the enabled column value should be 0 or 1. You cannot put "true" or "false." Oracle only works with 1 or 0. If you are using MySQL you can go with "true" or "false" so just be aware of this.

Also direct passwords should never be saved into database. Always it's a best practice to hash the passwords before saving to database. But in this article to keep it simple i'm saving passwords directly in the database. You should not do the same for real time applications. Any hashing mechanism can be applied to store and read passwords and it is out of scope in this article.

User Roles table with roles added for the above two users.


User roles

User roles



With this our work in database is completed. Now let's add JDBC driver and Spring JDBC dependencies into our application.

Java
 




xxxxxxxxxx
1
10


 
1
<dependency>
2
   <groupId>org.springframework</groupId>
3
   <artifactId>spring-jdbc</artifactId>
4
   <version>4.1.5.RELEASE</version>
5
</dependency>
6
<dependency>
7
   <groupId>com.oracle</groupId>
8
   <artifactId>ojdbc6</artifactId>
9
   <version>11.2.0.3</version>
10
</dependency>






xxxxxxxxxx
1
10


 
1
<dependency>
2
   <groupId>org.springframework</groupId>
3
   <artifactId>spring-jdbc</artifactId>
4
   <version>4.1.5.RELEASE</version>
5
</dependency>
6
<dependency>
7
   <groupId>com.oracle</groupId>
8
   <artifactId>ojdbc6</artifactId>
9
   <version>11.2.0.3</version>
10
</dependency>


Also make sure shared libraries also added for the dependencies we added.

Java
 




xxxxxxxxxx
1
30


1
      <sharedLibraries>
2
      <sharedLibrary>
3
       <groupId>org.springframework.security</groupId>
4
       <artifactId>spring-security-core</artifactId>
5
      </sharedLibrary>
6
      <sharedLibrary>
7
       <groupId>org.springframework.security</groupId>
8
       <artifactId>spring-security-config</artifactId>
9
      </sharedLibrary>
10
      <sharedLibrary>
11
       <groupId>org.springframework</groupId>
12
       <artifactId>spring-context</artifactId>
13
      </sharedLibrary>
14
      <sharedLibrary>
15
       <groupId>org.springframework</groupId>
16
       <artifactId>spring-beans</artifactId>
17
      </sharedLibrary>
18
      <sharedLibrary>
19
       <groupId>org.springframework</groupId>
20
       <artifactId>spring-core</artifactId>
21
      </sharedLibrary>
22
      <sharedLibrary>
23
       <groupId>org.springframework</groupId>
24
       <artifactId>spring-jdbc</artifactId>
25
      </sharedLibrary>
26
      <sharedLibrary>
27
       <groupId>com.oracle</groupId>
28
       <artifactId>ojdbc6</artifactId>
29
      </sharedLibrary>
30
   </sharedLibraries>



With this, we have everything we need to add the JDBC authentication manager. Let's go back to spring-beans.xml file and add the JDBC authentication manager. After adding our Spring beans file will look like below.

Java
 




xxxxxxxxxx
1
41


 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<beans xmlns="http://www.springframework.org/schema/beans"
3
  xmlns:context="http://www.springframework.org/schema/context"
4
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5
  xmlns:jdbc="http://www.springframework.org/schema/jdbc"
6
  xmlns:ss="http://www.springframework.org/schema/security"
7
  xsi:schemaLocation="http://www.springframework.org/schema/beans
8
    http://www.springframework.org/schema/beans/spring-beans.xsd
9
      http://www.springframework.org/schema/jdbc
10
    http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
11
    http://www.springframework.org/schema/context
12
    http://www.springframework.org/schema/context/spring-context.xsd
13
    http://www.springframework.org/schema/security
14
    http://www.springframework.org/schema/security/spring-security.xsd">
15
    
16
<bean id="datasource" name="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
17
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
18
        <property name="url"
19
   value="jdbc:oracle:thin:@harsha:1525:test" />
20
  <property name="username" value="test" />
21
  <property name="password" value="test01" />
22
    </bean>
23
    
24
    <ss:authentication-manager alias="authenticationManager" id="authenticationManager">
25
  <ss:authentication-provider>
26
   <ss:jdbc-user-service data-source-ref="datasource" id="jdbcService"
27
    users-by-username-query="select username,password, enabled from users where username = ?" 
28
    authorities-by-username-query="select username,authority from user_roles where username= ?" />
29
  </ss:authentication-provider>
30
 </ss:authentication-manager>
31
    
32
 <!--ss:authentication-manager alias="authenticationManager" id="authenticationManager">
33
  <ss:authentication-provider>
34
   <ss:user-service id="userService">
35
           <ss:user name="admin" password="admin" authorities="ROLE_ADMIN" /> 
36
           <ss:user name="harsha" password="welcome" authorities="ROLE_USER" />  
37
          </ss:user-service>
38
  </ss:authentication-provider>
39
 </ss:authentication-manager -->
40
 
41
</beans>



In the above code snippet, from line number 16 to 22, I have added my Oracle DB details. From line 24 to 30, I used the data source defined to create authentication provider which queries the database with user name and password provided by the user in the basic auth section when a call is made. If the username and password are correct, then roles will be retrieved from the user roles table and provided to the Spring authorization filter in our flow. Thats it. With this all our code changes are completed. Now we need to run the application and test our flow.

Important Note: I have added lot of Spring namespaces in the Spring beans file in order for security to work. I have taken those from official Mule documentation. Make sure you have all those namespaces added or else you might get some exceptions.

Now it's time to test our work.

First, let's try with the user "Matt." This user doesn't have ROLE_ADMIN role. so he should not be able to access the flow.

Running with user Matt

Running with user Matt


As you can see Matt was able to login successfully but he cannot access the flow as he needs role "ROLE_ADMIN" to access.

Now let's test with user "harsha." He should be able to access as he has required role.

Running with user harshaRunning with user harsha



As expected user "harsha" can access the flow and we can see the "Hello World" response.

We can use any database we want with minor modifications to the spring-beans file. I have tested with Oracle and MySQL and I was able to get the security to work.

Please provide feedback through comments in case you see any issues with the article. 

You can download code here.

 

 

 

 

Top