Friday, January 11, 2013

Multiple User Stores configuration in WSO2 Identity Server

You know wso2 products are very smart and customizable products. Here I'm going to explain one of another smart features came up with wso2 products. As a example will take WSO2 Identity server as a product.

Lets look at one of simple business scenarios.

1. I need connect multiple user stores.
ex/ different domain users in different databases to one single product.
2. All users can access same wso2 product (IS).

Multiple User Stores

First of all we need to do some configuration in Identity Server. Refer this post for additional information about data base configuration with wso2 products.

You have to create two databases in Mysql as FOO and BAR with database table structure. You can simply do this as follows.
Go to mysql command line and create two databases.
[sourcecode language="sql"]
mysql > create database FOO;
mysql > create database BAR;
[/sourcecode]

Go to command line and run the following commands to create the table structure.
[sourcecode language="bash"]
> mysql -u username -p FOO < $IS_HOME/dbscripts/mysql.sql
[/sourcecode]

[sourcecode language="bash"]
> mysql -u username -p BAR < $IS_HOME/dbscripts/mysql.sql
[/sourcecode]

Now we created databases properly.

1. master-datasource.xml - we have to configure three data sources for H2, FOO, BAR databases.

[sourcecode language="xml"]
<datasources>      
        <datasource>
            <name>WSO2_CARBON_DB</name>
            <description>The datasource used for registry and user manager</description>
            <jndiConfig>
                <name>jdbc/WSO2CarbonDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:h2:repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
                    <username>wso2carbon</username>
                    <password>wso2carbon</password>
                    <driverClassName>org.h2.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>

       <datasource>
            <name>WSO2_MySQL_FOO_DB</name>
            <description>The datasource used for user manager bar.com</description>
            <jndiConfig>
                <name>jdbc/WSO2MySqlFooDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/FOO</url>
                    <username>root</username>
                    <password>root</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>

       <datasource>
            <name>WSO2_MySQL_BAR_DB</name>
            <description>The datasource used for user manager bar.com</description>
            <jndiConfig>
                <name>jdbc/WSO2MySqlBarDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/BAR</url>
                    <username>root</username>
                    <password>root</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>
[/sourcecode]

2. user-mgt.xml - Have to refer created data sources for specific domains.
The first user store configuration take as primary user store and others are secondary.
In the primary user store we are not going to specify the domain name.

[sourcecode language="xml"]
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager">
<Property name="defaultRealmName">WSO2.ORG</Property>
<Property name="kdcEnabled">false</Property>
<Property name="ConnectionURL">ldap://localhost:${Ports.EmbeddedLDAP.LDAPServerPort}</Property>
<Property name="ConnectionName">uid=admin,ou=system</Property>
<Property name="ConnectionPassword">admin</Property>
<Property name="passwordHashMethod">SHA</Property>
<Property name="UserNameListFilter">(objectClass=person)</Property>
<Property name="UserEntryObjectClass">scimPerson</Property>
<Property name="UserSearchBase">ou=Users,dc=wso2,dc=org</Property>
<Property name="UserNameSearchFilter">(&amp;(objectClass=person)(uid=?))</Property>
<Property name="UserNameAttribute">uid</Property>
<Property name="PasswordJavaScriptRegEx">^[\\S]{5,30}$</Property>
<Property name="ServicePasswordJavaRegEx">^[\\S]{5,30}$</Property>
<Property name="ServiceNameJavaRegEx">^[\\S]{2,30}/[\\S]{2,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UsernameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="ReadLDAPGroups">true</Property>
<Property name="WriteLDAPGroups">true</Property>
<Property name="EmptyRolesAllowed">true</Property>
<Property name="GroupSearchBase">ou=Groups,dc=wso2,dc=org</Property>
<Property name="GroupNameListFilter">(objectClass=groupOfNames)</Property>
<Property name="GroupEntryObjectClass">groupOfNames</Property>
<Property name="GroupNameSearchFilter">(&amp;(objectClass=groupOfNames)(cn=?))</Property>
<Property name="GroupNameAttribute">cn</Property>
<Property name="MembershipAttribute">member</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="UserDNPattern">uid={0},ou=Users,dc=wso2,dc=org</Property>
<Property name="SCIMEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
</UserStoreManager>

<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
<Property name="dataSource">jdbc/WSO2MySqlFooDB</Property>
<Property name="DomainName">foo.com</Property>
</UserStoreManager>

<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
<Property name="dataSource">jdbc/WSO2MySqlBarDB</Property>
<Property name="DomainName">bar.com</Property>
</UserStoreManager>
[/sourcecode]

Once you done above configurations you can start the Identity server.

3. Log in to the IS (username :admin, password : admin)
Configuration ->Users and Roles
is

Select Users->Add new Users
is

Now you can create the user in different domains.

[username :test password :test123] - it will store at primary user store.
as well as you can create User with specifying the domain. then it will store at specified domain user store.
[username :foo.com/dinuka password:dinuka ]
[username :bar.com/malinda password:malinda]

is

is

once you done this you have to go to Roles and give the login permission to everyone role.
is

Now you can log in to the IS with any user in primary or secondary user store either specifying the domain name or without domain name.

[username :foo.com/dinuka password : dinuka] or
[username :dinuka password : dinuka]
Once you try to log in to the system with specifying the domain, IS will look at the specified domain user store to authenticate the user.
other wise it will go through all the define user stores starting from primary user store.

is

is

2 comments:

  1. masterdatasource available @ $IS_HOME/repository/conf/datasources

    ReplyDelete
  2. [...] to connect to the two user stores as primary and secondary. you bettor read my early blog post call (Multiple User Stores configuration in WSO2 Identity Server) but there is lot of api changes in 4.1.1 [...]

    ReplyDelete