Configuring External User Stores
The WSO2 User Manager authenticates users from different types of user stores and currently has the capability to easily plug-in to LDAP, Active Directory and JDBC to perform authentication.
All WSO2 Carbon based products can read and write users and roles from external LDAP user stores. You can configure Carbon products to access LDAP or JDBC using one of the following modes.
Read-Only Mode
All WSO2 Carbon based products can read users and roles from external LDAP/Active Directory user stores.
To configure an external LDAP user store/active directory user store:
You can configure Carbon products to read users/roles from your company LDAP. The "Read Only" mode does not write any data into the LDAP.
Note that LDAP is used going forward to refer to both LDAP and ActiveDirectory servers.
Step 1 : Backup <carbon-home>/repository/conf/user-mgt.xml.
- A sample file for LDAP user store is given below:
<UserManager> <Realm> <Configuration> <AdminRole>admin</AdminRole> <AdminUser> <UserName>admin</UserName> <Password>XXXXXX</Password> </AdminUser> <EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in thsi role sees the registry root --> <Property name="dataSource">jdbc/WSO2CarbonDB</Property> <Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property> </Configuration> <UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadOnlyLDAPUserStoreManager"> <Property name="TenantManager">org.wso2.carbon.user.core.tenant.CommonHybridLDAPTenantManager</Property> <Property name="ConnectionURL">ldap://localhost:10389</Property> <Property name="ConnectionName">uid=admin,ou=system</Property> <Property name="ConnectionPassword">admin123</Property> <Property name="UserSearchBase">ou=system</Property> <Property name="UserNameListFilter">(objectClass=person)</Property> <Property name="UserNameAttribute">uid</Property> <Property name="ReadLDAPGroups">false</Property> <Property name="GroupSearchBase">ou=system</Property> <Property name="GroupNameSearchFilter">(objectClass=groupOfNames)</Property> <Property name="GroupNameAttribute">cn</Property> <Property name="MembershipAttribute">member</Property> </UserStoreManager> </Realm> </UserManager>
- A sample file for Active Directory is given below:
<UserManager> <Realm> <Configuration> <AdminRole>admin</AdminRole> <AdminUser> <UserName>admin</UserName> <Password>XXXXXX</Password> </AdminUser> <EveryOneRoleName>everyone</EveryOneRoleName> <!-- By default users in thsi role sees the registry root --> <Property name="dataSource">jdbc/WSO2CarbonDB</Property> <Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property> </Configuration> <!-- Active directory configuration follows --> <UserStoreManager class="org.wso2.carbon.user.core.ldap.ActiveDirectoryUserStoreManager">> <Property name="TenantManager">org.wso2.carbon.user.core.tenant.CommonHybridLDAPTenantManager</Property> <Property name="ConnectionURL">ldap://10.100.1.211:389</Property> <Property name="ConnectionName">cn=Administrator,cn=users,dc=wso2,dc=lk</Property> <Property name="ConnectionPassword">admin123</Property> <Property name="UserSearchBase">cn=users,dc=wso2,dc=lk</Property> <Property name="UserNameListFilter">(objectClass=person)</Property> <Property name="UserNameAttribute">sAMAccountName</Property> <Property name="ReadLDAPGroups">true</Property> <Property name="GroupSearchBase">cn=users,dc=wso2,dc=lk</Property> <Property name="GroupNameSearchFilter">(objectcategory=group)</Property> <Property name="GroupNameAttribute">cn</Property> <Property name="MembershipAttribute">member</Property> </UserStoreManager> </Realm> </UserManager>
Copy the user-mgt-ldap.xml file and save it as <carbon-home>/repository/conf/user-mgt.xml. When you are configuring for ActiveDirectory, do the same to user-mgt-actdir.xml.
Note the following in your file.
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadOnlyLDAPUserStoreManager">
Step 2 : Find a valid user that resides in the Directory Server. For example, let's say a valid user name is "AdminSOA". Update the Admin user section of your ldap configuration as follows. You don't have to update the password element; leave it as it is.
<AdminUser> <UserName>AdminSOA</UserName> <Password>XXXXXX</Password> </AdminUser>
Step 3 : Update the connection details to suit your Directory Server.
<Property name="ConnectionURL">ldap://localhost:10389</Property>
Step 4 : Obtain a user who has permission to read all users/attributes and perform searches on the Directory Server from your LDAP administrator. For example, let's say the privileged user is "AdminLDAP" and password is "2010#Avrudu". Now update the following sections of the realm configuration.
<Property name="ConnectionName">uid=AdminLDAP,ou=system</Property> <Property name="ConnectionPassword">2010#Avrudu</Property>
Update the <Property name="UserSearchBase"> by giving the directory where the users are stored. LDAP searches for users will start from this location.
Property name="UserSearchBase">ou=system</Property>
Step 5 : Set the attribute that you wish to be used as the username. The most common case is to use either "cn" or "uid" as the username. If you are not sure what attribute is available in your LDAP, check with your LDAP administrator.
<Property name="UserNameAttribute">uid</Property>
For Active Directory this is different.
<Property name="UserNameAttribute">sAMAccountName</Property>
Step 6 : This is the most basic configuration. For more advanced options like "external roles", jump to step 7. Otherwise you are done! Now start your server and try to login as "AdminSOA". The password is the AdminSOA's password in the LDAP server.
If you are unable to login, contact the WSO2 carbon user group according to the contact details given under "community and support" section on the welcome page.
Step 7 : The realm can read roles from the Directory Server. It can read user/role mapping based on a backlink attribute or membership (user list) attribute.
- Step 7.1 : Reading roles based on a membership attribute. This is used by the ApacheDirectory server and OpenLDAP.
<Property name="ReadLDAPGroups">false</Property> <Property name="GroupSearchBase">ou=system</Property> <Property name="GroupSearchFilter">(objectClass=groupOfNames)</Property> <Property name="GroupNameAttribute">cn</Property> <Property name="MembershipAttribute">member</Property>
- Step 7.2 : Reading roles based on a backlink attribute. This is used by the Active Directory.
<Property name="ReadLDAPGroups">true</Property> <Property name="GroupSearchBase">cn=users,dc=wso2,dc=lk</Property> <Property name="GroupSearchFilter">(objectcategory=group)</Property> <Property name="GroupNameAttribute">cn</Property> <Property name="MemberOfAttribute">memberOf</Property>
The following table contains detail descriptions of each property.
Property Name | Description |
---|---|
MaxUserNameListLength | |
ConnectionURL | The connection URL to the database. |
ConnectionName | The user name used to connect to the database. |
ConnectionPassword | Password of the connection username. |
UserSearchBase | Search base of users. |
UserNameListFilter | The LDAP query that should be used to search users. |
UserNameAttribute | Users can be authenticated using their email address, uid and etc. |
ReadLDAPGroups | Indicates whether to read groups from the LDAP. |
GroupSearchBase | Search base for groups. |
GroupNameListFilter | |
GroupSearchFilter | The LDAP query used to search for groups. |
GroupNameAttribute | The attribute to be treated as the group name. |
MembershipAttribute | Attribute that contains users. |
UserRolesCacheEnabled | |
ReplaceEscapeCharactersAtUserLogin |
Read/Write Mode
If you wish to connect to external LDAP user store such that only the user entries are written to external LDAP and roles are not written to external LDAP, the only difference from the steps in section "Read-Only Mode" is in following:
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager">
<CARBON_HOME>/repository/conf/user-mgt.xml
file has a commented out configuration for external LDAP user stores.
1. Enable the <ReadWriteLDAPUserStoreManager> element in the user-mgt.xml file. When it is enabled, the user manager reads/writes into the LDAP user store.
2. The default configuration for external read/write LDAP user store in user-mgt.xml file is as follows. Change the values according to your requirement.
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager"> <Property name="TenantManager">org.wso2.carbon.user.core.tenant.CommonHybridLDAPTenantManager</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">wso2Person</Property> <Property name="UserSearchBase">ou=Users,dc=wso2,dc=org</Property> <Property name="UserNameSearchFilter">(&(objectClass=person)(uid=?))</Property> <Property name="UserNameAttribute">uid</Property> <Property name="PasswordJavaScriptRegEx">[\\S]{5,30}</Property> <Property name="UsernameJavaScriptRegEx">[\\S]{3,30}</Property> <Property name="UsernameJavaRegEx">^[^~!@#$;%^*+={}\\|\\\\<>,\'\"]{3,30}$</Property> <Property name="RolenameJavaScriptRegEx">[\\S]{3,30}</Property> <Property name="RolenameJavaRegEx">^[^~!@#$;%^*+={}\\|\\\\<>,\'\"]{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">(&(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> </UserStoreManager>
Main elements of the configuration can be explained as follows.
Property Name | Description |
---|---|
ConnectionURL | Connection URL to the ldap server. In the case of default LDAP in carbon, port is mentioned in carbon.xml and a reference to that port is mentioned in the above configuration. |
ConnectionName | This should be the DN (Distinguish Name) of the admin user in LDAP. |
ConnectionPassword | Password of the admin user. |
passwordHashMethod | Password Hash method when storing user entries in LDAP. |
UserNameListFilter | Filtering criteria for listing all the user entries in LDAP. |
UserEntryObjectClass | Object Class used to construct user entries. In the case of default LDAP in carbon, it is a custom object class defined with the name-'wso2Person' |
UserSearchBase | DN of the context under which user entries are stored in LDAP. |
UserNameSearchFilter | Filtering criteria for searching a particular user entry. |
UserNameAttribute | Attribute used for uniquely identifying a user entry. Users can be authenticated using their email address, uid and etc. |
| Policy that defines the password format. |
UsernameJavaScriptRegEx | The regular expression used by the font-end components for username validation. |
UsernameJavaRegEx | A regular expression to validate usernames. By default, strings having length 5 to 30 non-empty characters are allowed. |
RolenameJavaScriptRegEx | The regular expression used by the font-end components for rolename validation. |
RolenameJavaRegEx | A regular expression to validate rolenames. By default, strings having length 5 to 30 non-empty characters are allowed. |
ReadLDAPGroups | Specifies whether groups should be read from LDAP. |
WriteLDAPGroups | Specifies whether groups should be written to LDAP. |
EmptyRolesAllowed | Specifies whether underlying LDAP user store allows empty groups to be created. In the case of ldap in carbon, the schema is modified such that empty groups are allowed to be created. Usually LDAP servers do not allow to create empty groups. |
GroupSearchBase | DN of the context under which user entries are stored in LDAP. |
GroupNameListFilter | Filtering criteria for listing all the group entries in LDAP. |
GroupEntryObjectClass | Object Class used to construct user entries. |
GroupNameSearchFilter | Filtering criteria for searching a particular group entry. |
GroupNameAttribute | Attribute used for uniquely identifying a user entry. |
MembershipAttribute | Attribute used to define members of LDAP groups. |
UserRolesCacheEnabled | This is to indicate whether to cache the role list of a user. By default it is 'true'. Set it to 'falese' if user-roles are changed by external means and those changes should be instantly reflected in the carbon instance. |
UserDNPattern | The patten for user's DN. It can be defined to improve the LDAP search. When there are many user entries in the LADP, defining a "UserDNPattern" provides more impact on performances as the LDAP does not have to travel through the entire tree to find users. |
How to Configure an External JDBC User Store
All Carbon based products can work with external RDBMSs. You can configure Carbon to read users/roles from your company RDBMS and even write to it. Therefore, the user core connected to two databases.
- Carbon database where authorization information is stored in the internal Carbon database.
- Your company database where users/roles resides.
So the user-mgt.xml file must contain details for two database connections. The connection details mentioned earlier is used by the Authorization manager. If we specify another set of database connection details inside UserStoreManager, it will read/write users to that database. Step by step guidelines for connecting to an external JDBC user store in read-only mode is given below.
Step 1 : Back-up the <carbon-home>/repository/conf/user-mgt.xml file. A sample file for JDBC user store (user-mgt-jdbc.xml) is available in <carbon-home>/repository/conf
directory. Download the relevant file and save it as <IS_HOME>/repository/conf/user-mgt.xml
. Uncomment the following section in your file if it is commented out.
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
Step 2 : Find a valid user that resides in the RDBMS. For example, say a valid username is AdminSOA. Update the Admin user section of your ldap configuration as follows. You do not have to update the password element; leave it as it is.
<AdminUser> <UserName>AdminSOA</UserName> <Password>XXXXXX</Password> </AdminUser>
Step 3 : In the user-mgt.xml file, add passwordHashMethod property within the JDBCUserStoreManager. For example:
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager"> <Property name="passwordHashMethod">SHA</Property> ... </UserStoreManager>
The passwordHashMethod property specifies how the password should be stored, and usually has the values:
- SHA - Uses SHA digest method.
- MD5 - Uses MD 5 digest method.
- PLAIN_TEXT - Plain text passwords.
- In addition, it also supports all digest methods in http://docs.oracle.com/javase/6/docs/api/java/security/MessageDigest.html.
Step 4 : Update connection details inside the <UserStoreManager> class.
Step 5 : In the user-mgt.xml file, under realm configuration, set the value of MultiTenantRealmConfigBuilder property to org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder. For example,
<Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.SimpleRealmConfigBuilder</Property>
Step 6 : Add the JDBC driver to the classpath by dropping the Jar to the <carbon-home>/repository/components/lib
directory.
Step 7 : Edit the SQLs in the user-mgt.xml file according to your requirements, and start the server.