How to Implement Custom User Store Manager for WSO2 Servers

According to the WSO2 Identity Server product page, It supports for LDAP, AD and JDBC based user stores. And also It said that it has capability to plug custom user stores. What is mean by custom user stores? It can be anything such as NoSQL (Cassandra), Legacy user store, JDBC user store with different schema…. If you need to plug a custom user store, Best way is to implement the abstract method with is given by the AbstactUserStoreManager class. Most of the cases, custom user store means a JDBC based user store with different schema. WSO2 Identity Server provides a JDBC based user store with default schema (its own schema). If your enterprise does not have user store or needs new user store, Then Default schema can be used without any modifications… But most of the cases, enterprise already have an existing user store. Then want to plug their user store with WSO2 Identity server (To achieve SSO, XACML, API capabilities). Also, enterprise does not want to write to their user store for WSO2 Identity Server, Because they may have already built homegrown system to manage user store. Therefore, mostly enterprise user store must be plugged as read user store.

Use Case

Lets think about small use case and try to build a custom user store manager.

Assume, enterprise has MySQL user store that can be represented by one table.. SQL schema would be as following. This table contain user name (unique id for user) , plain text password and the user’s attributes

CREATE TABLE SAMPLE_USER (
	USERNAME char(50),
	PASSWORD char(50),
	EMAIL char(50),
	FIRSTNAME char(50),
	LASTNAME char(50),
	MOBILE char(50),
	PRIMARY KEY (USERNAME)
);

Sample table structure would be as following

Step1. You can create a database in the MySQL server.  Let say  sampleuserstore

Step2. Use this sample script to create the user store

>mysql -u root -p sampleuserstore < [path to SQL script]

How to Configure

Sample user store manager that has been developed for above user store can be found at here. This user manager would work with WSO2IS 4.5.0/4.6.0/4.7.0 versions.

Step1. Extract fresh copy of wso2is-4.5.0.zip

Step2. Lets create a datasource for our sample user store database sampleuserstore. You can configure a datasource in master-datasources.xml file which can be found at IS_HOME/repository/conf/datasources directory

eg: sample configuration for datasource would be as following…. You can configure this in master-datasources.xml file.  Modified master-datasources.xml file which can be found at resources directory

<datasource>
 <name>USER_STORE_DB</name>
 <description>The datasource used for registry and user manager</description>
 <jndiConfig>
 <name>jdbc/UserStoreDB</name>
 </jndiConfig>
 <definition type="RDBMS">
 <configuration>
 <url>jdbc:mysql://localhost:3306/sampleuserstore</url>
 <username>root</username>
 <password>asela</password>
 <driverClassName>com.mysql.jdbc.Driver</driverClassName>
 <maxActive>50</maxActive>
 <maxWait>60000</maxWait>
 <testOnBorrow>true</testOnBorrow>
 <validationQuery>SELECT 1</validationQuery>
 <validationInterval>30000</validationInterval>
 </configuration>
 </definition>
 </datasource>

Step3. Configure user-mgt.xml file which can be found at IS_HOME/repository/conf directory

1. Select Identity Server’s administrator user name from the sample user store. you need to select one user name and configure it in following place. Here password is not needed to configure as it can be read from the user store.

<AdminUser>
 <UserName>testadmin</UserName>
 <Password></Password>
 </AdminUser>

2. Disable (comment) default user store configuration and configure new user store configuration for sample user store such as follows

There are two points are important when configuring

  • User store is connected as read only mode. Therefore following property must be there.
<Property name="ReadOnly">true</Property>
  • User store does not has groups. Therefore Identity Server can not read groups from the user store
<Property name="ReadGroups">false</Property>
  • Data source configuration must be pointed to the data source that has been configured earlier

Sample configuration would be as following… Modified user-mgt.xml file which can be found at resources directory

<UserStoreManager class="org.soasecurity.sample.jdbc.user.store.SampleReadOnlyJDBCUserStoreManager">
 <Property name="TenantManager">org.wso2.carbon.user.core.tenant.JDBCTenantManager</Property>
 <Property name="ReadOnly">true</Property>
 <Property name="ReadGroups">false</Property>
 <Property name="UserRolesCacheEnabled">true</Property>
 <Property name="MaxRoleNameListLength">100</Property>
 <Property name="MaxUserNameListLength">100</Property>
 <Property name="SelectUserSQL">SELECT * FROM SAMPLE_USER WHERE USERNAME=?</Property>
 <Property name="UserFilterSQL">SELECT USERNAME FROM SAMPLE_USER WHERE USERNAME LIKE ? ORDER BY USERNAME</Property>
 <Property name="IsUserExistingSQL">SELECT USERNAME FROM SAMPLE_USER WHERE USERNAME=? </Property>
 <Property name="dataSource">jdbc/UserStoreDB</Property>
 </UserStoreManager>

Step4. Copy org.wso2.soasecurity.sample.jdbc.user.store-1.0.0.jar which can be found at resources directory, to IS_HOME/repository/components/lib

Step5. Copy mysql-connector-java-5.1.10-bin.jar which can be found at resources directory, to IS_HOME/repository/components/lib

Step6. Start the server

Step7. You can login to management console with the admin user that is defined in the user-mgt.xml file.

Step8. If you want to see attributes in the user profile,  You can use claim management to map claim uri with attribute values. More details on claim management can be found here

Note :  When Identity Server 450 is started, You would see some error message in the start up console. This is a know issue with 450. You can find the public jira from here. This has been fixed in 460 version.