In WSO2 Identity Server, the Tenant Domains List Dropdown feature [2] is useful when the users may login to different tenants for authentication in a scenario where a SAAS is enabled in the Service Provider.
However in order to enable this feature, we need to set many configuration changes and also enable Mutual SSL authenticator in the Identity Server. If the environment is clustered having multiple Identity Server nodes, then we need to add several other configurations also to communicate between the servers to keep the active tenant domains list consistent among the nodes. When the cluster is fronted by a Load Balancer like Amazon ELB, there can be problem due to not supporting certificate based authentication (Mutual SSL).
However instead of using this feature, we can get the same output by writing a custom authenticator where inside the authenticator’s code, it can get the list of active tenants and send the list to the login page of the authentication endpoint webapp. Then in the login page, it can extract the tenant list and display in a dropdown. From the authenticator to the authentication endpoint webapp, the tenant list will be sent through a query parameter. When there are many tenants created, this will not be a good solution as the URL size increases.
However this solution would be useful in a scenario like below.
- The server is configured with multi step authentication.
- Assume the authentication Step 1 is a federated authenticator.
- User first logs into the federated authenticator.
- Then Identity Server receives claims from the federated authenticator in authentication Step 1.
- Based on some claim, inside the authentication Step 2 which is the custom authenticator (local), we can take a decision on which tenants to display. This can be based on the roles that the user (logged into Step 1) has.
- In such case, we can display a subset of all the active tenants where the user has some association with.
In a scenario like above, instead of using the Tenant Domains List Dropdown feature which Identity Server provides, we can implement our own custom authenticator and get our requirements satisfied.
In this blog post, I am providing a sample maven project and demonstrate how to get the tenant list displayed in the login page of authentication endpoint webapp.
For the demonstration I am using the Identity Server 5.0.0 version with Service Pack 1 installed.
First you need to clone the Github repository [2] which has the required resources. The maven project of the custom authenticator is the directory with name MyCustomAuthenticator [3]. You can build this project and get the jar file of the autheticator. Or else you can use the pre-built org.wso2.carbon.identity.application.authenticator.mycustomauthenticator-4.2.2.jar file available in the target directory of the project.
Copy the org.wso2.carbon.identity.application.authenticator.mycustomauthenticator-4.2.2.jar file into the IS_HOME/repository/components/dropins directory. (This is because the authenticator is written as an OSGI bundle).
Next step is to copy the two files in “AuthenticationEndpoint Webapp Changes” [4] directory to IS_HOME/repository/deployment/server/webapps/authenticationendpoint/ directory. Here you will be replacing the login.jsp file which is already existing. The customauth.jsp file is a new file which has the UI related to the authenticator. The only change in the login.jsp is that it checks the name of the authenticator and if it is our custom authenticator, then it includes the customauth.jsp file to be displayed.
Now we have done all the changes. Restart the Identity Server.
Then we need to setup a client application which uses Identity Server for authentication. For that, I am setting up the travelocity sample webapp following the steps described in [5].
In the Service Provider, I have enabled ‘Saas Application’ so that users from any tenant can authenticate with this Service Provider.
If you login to the travelocity.com sample application, you will see the usual login page because by default, the Basic Authenticator is used for authentication in the Service Provider.
Now we need to engage our custom authenticator with the Service Provider. Edit the Service Provider configuration and expand the ‘Local & Outbound Authentication Configuration’ section.
In the dropdown associated with the Local Authentication, it should list our custom authenticator with the name ‘custom’. Select the radio button ‘Local Authentication’ and from the authenticators dropdown, select the custom authenticator. Then save the Service Provider configuration. (If you want to use this for a scenario like multi step authentication, then you need to select ‘Advanced Configuration’ and setup this authenticator in a particular step).
Now try to login again to the travelocity.com sample. Then if you do not have any tenants created in the Identity Server, or if you do not have any active tenant (other than super tenant), you will see the below login page. This is loaded from the customauth.jsp file we added to authenticationendpoint webapp previously. You can change the styles as you wish.
If you have active tenants, then those will be displayed in a dropdown in the login page. By default there will be ‘Super Tenant’ in the list which is added from the customauth.jsp.
You can select a particular tenant from the dropdown.
As the username, you do not need to append the tenant domain now. Just type the username (without @tenantdomain), enter the password and you should be able to login to the travelocity sample app.
This way you can get the same functionality as Tenant Domains List Dropdown feature without any configuration other than Service Provider’s configuration.
If we talk about the technical aspects of this, inside the MyCustomAuthenticato.java [6] it has initiateAuthenticationRequest method where it retrieves the list of active tenants and sends to the authenticationendpoint as a query parameter with the name tenantList. The value is a comma separated string with all active tenant domains. Then inside the authenticationendpoint webapp, in customauth.jsp file, it retrieves this query parameter, split the string with “,” delimiter and load the tenant domain names to a dropdown in the UI.
So, in a usecase like multi step authentication which I mentioned previously, what you can do is, after the Step1 (federated authenticator) authentication, you can retrieve claims from the IDP. For example you may retrieve a role claim, and then inside this custom authenticator which is the Step2 of our authentication sequence in that usecase, you can access that particular claim received in previous step and take a decision. An example is based on the roles the user is granted, select a subset of tenants which are related to the user. And then send the list to the authenticationendpoint so that this user will not see all available tenants, instead the user will see a the particular set of tenants which the user is related to.
There can be many usecases where this kind of an implementation would be useful. You can refer to the code and modify it according to your requirements.
References :
Tharindu Edirisinghe
Identity Server Team
WSO2