How to configure your preferred user stores to authenticate users
WSO2 Identity server allows keeping multiple user stores for your system to store users and their roles. There should be one primary user store (mandatory) and any number of secondary user stores(optional). When creating a secondary user store we can provide a user store domain name for the secondary user stores. “PRIMARY” is the user store domain of the primary user store.
Now think about a service provider who uses WSO2 Identity Server to authenticate users who log into the application and it maintains multiple user stores in IS.
Now we are going to look at two different ways that users can provide their usernames during the login process:
- The user provides the user name with the user store domain (eg: PRIMARY/peter). Then WSO2 IS validate username and password against the values stored in the PRIMARY user store.
- The user provides only the username without specifying the user store domain (eg: peter). Then, WSO2 IS starts to authenticate the user starting from the PRIMARY user store. If one user store fails to authenticate the user even if there is the username(i.e password is not matching), authentication will be executed in chained UserStoreManagers recursively.
You can understand the second point from the highlighted lines in the codebase.
Let’s say the service provider now wants to narrow down the number of user stores that will be searched to authenticate a user when he/she doesn’t provide user store domain-specific username. How can we do this ??
NOTE: This feature is available in IS-5.7.0 WUM updated version and IS-5.9.0 onwards
Let’s head-on with the following example to understand this process more clearly.
Identity Server — Product-IS 5.9.0 (download here)
Service provider — travelocity.com (deploy it according to the given instructions here)
Three Secondary JDBC user stores Named: “DRIVER”, “MANAGER”, “CUSTOMER” (instructions: here)
Add users according to the following table: (instructions: here)
Authenticating condition: Only the users in PRIMARY, DRIVER and MANAGER user store can access travelocity.com services. Users in the CUSTOMER user store can’t use services in travelocity.com.
Moreover, users don’t know their user store domain. Thus, they input username without the user store domain. (i.e username is just ‘peter’ not like ‘MANAGER/peter’).
Without any further configurations, try to login to travelocity.com app and using four different username-password combinations in the table. You will be succeeded.
Let’s narrow down the number of user stores allowed for travelocity.com login.
You need to do two things:
- Implement UserStorePreferenceOrderSupplier interface with your own logic to retrieve the allowed user stores.
2. Then extend CallBackHandlerFactory and create an object of your custom UserStorePreferenceOrderSupplier.
This is the logic implemented according to the above requirement.
CustomUserStoreOrderCallbackFactory
class extendsCallBackHandlerFactory
.SimpleUserStoreOrderCallbackHandler
implementsUserStorePreferenceOrderSupplier<List<String>>
.RegistryBasedUserStoreOrderCallbackHandler
extendsSimpleUserStoreOrderCallbackHandler
.- Logic: Users who are in PRIMARY, MANAGER, and DRIVER user stores can log in to travelocity.com service provider. This
configuration is read from Registry.
NOTE: in the pom.xml file, you need to update the org.wso2.carbon.identity.framework dependency version according to the IS pack you are using.
<dependency>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.identity.application.authentication.framework</artifactId>
<version>5.14.97</version>
</dependency>
Also, Make sure the carbon-kernal which is used in the IS pack lies in the defined range.
<carbon.kernel.package.import.version.range>[4.4.0, 5.0.0)</carbon.kernel.package.import.version.range>
NOW what should we do ??
- Build the repo which contains the login using
mvn clean install
command. - Inside target folder, you will find
org.wso2.carbon.identity.custom.callback.userstore-1.0-SNAPSHOT.jar
- Copy and paste the generated jar file
“ org.wso2.carbon.identity.custom.callback.userstore-1.0-SNAPSHOT.jar”
into<IS-HOME>/repository/components/dropins/
- Configure the extended CallBackHandlerFactory in
<IS-HOME>/repository/conf/identity/application-authentication.xml
file, under
<ApplicationAuthentication xmlns=” http://wso2.org/projects/carbon/application-authentication.xml “>
<Extensions>
…
<CallbackFactory>org.wso2.carbon.identity.custom.callback.userstore.CustomUserStoreOrderCallbackFactor
y</CallbackFactory>
…
</Extensions>
NOTE: From IS-5.10.0 onwards this modification should be done through <IS-HOME>/repository/conf/deployment.toml
file. Add the following lines to deployment.toml.
[authentication.framework.extensions]
callback_factory = “org.wso2.carbon.identity.custom.callback.userstore.CustomUserStoreOrderCallbackFactory”
5. Start the server by issuing ./wso2server.sh
(Linux)/ ./wso2server.bat
(Windows) on terminal navigating to <IS-HOME>/bin
6. Navigate Main -> Registry -> Browse
and click on Browse.
7. Navigate to _system -> config
. You will find a file named userstore-metadata.xml
(This file is defined in the CustomCallbackUserstoreServiceComponent class as REG_PATH) Click on userstore-metadata.xml.
8. Click +
button in Properties
tab. It will appear as follows. These values will be used when authenticating users.
Now try to log into the travelocity.com using the username-password pairs we introduced at the beginning.
The result:
Users in PRIMARY/ MANAGER/ DRIVER user stores will log into the system.
Users in the CUSTOMER user store will fail to login.
We are done!! Don’t forget to applause if you get something by this blog.