For example, let’s say your system handles user login through 3 factorsāāāBasic credentials, face detection and a One-time-Password sent to the email. Now, if user A is accessing your system from the Company intranet, you may want to make the login process easier by skipping the One-time-Password. This pattern for the Administrator to conditionally enable/ disable steps in the login flow is formally defined as āConditional Authenticationā, and WSO2 Identity Server has come up with a neat feature to facilitate this.
I hope the following walkthrough will help you grasp this concept and use it wisely!
Background of the Sample
To demonstrate this feature, I will pick a scenario where a system has 2 authentication steps; Basic credentials and Email based One-Time-Password authentication. The example will be based on the case of the user trying to login to the system from public internet, or from the company intranet, so that, if the user is within the company intranet, this sample will skip the Email OTP authentication step. The condition will be based on the authentication requestās source IP address, inferred from the āx-forwarded-forā header.
Pre-requisites
- WSO2 Identity Server 5.6.0
- Nginx server (To simulate the x-forwarded-for header)
- Apache tomcat 9.x
- Google account with app permission: (You will need to create a test google account)
- Sample web application with SSO enabled
Sample Web application
You can download the war file I used here, or build it from the source by cloning from this repo.
Copy the built war file from above path to your tomcat webapps directory and make sure that it is deployed successfully.
** Going along WSO2 guidelines, I have used ālocalhost.comā in the webapp. Therefore, we need to add a mapping to it at the /etc/hosts file (in case of Linux) :
`127.0.0.1 localhost.com`
Identity server configuration
Email OTP configuration
We can follow the official WSO2 documentation to configure this. For reference, I have listed the changes to “repository/conf” directory here.
However, different to the document, we are using the newer SAML2 SSO sample web application. The Identity provider and service provider configuration from my setup is below:
Identity Provider required for federating EmailOTP to Google
Service Provider needed for the web application
Service ProviderāāāSAML SSO configuration
Service ProviderāāāLocal and Inbound Authentication Configuration
Now we can try out the login flow with URL āhttp://localhost.com:8080/saml2-web-app-dispatch.com“. You will see the below sequence:
*** Make sure to update the admin user’s email address to a valid email address so that you can retrieve the OTP code from the email.
Making things conditional
Custom Claim to hold the trusted values
We are trying to skip the OTP authentication if the userās IP address is a trusted one. So, we need a way to store each userās trusted IP address in their profile for comparison with incoming requests. Best way to do this is by using a custom claim.
1. Navigate to āClaimsā -> āAddā -> āAdd local claimā and create a claim with following attributes:
2. Since we have enabled the claim as a default attribute on user profile, you can update the test userās profile with the trusted IP address value:
Adding the authentication script
- Restart the Identity server as: āsh wso2server.sh -DenableConditionalAuthenticationFeatureā
- Once started you will be able to see below extra section below the authentication steps in the āLocal and Outbound Authentication Configurationā -> āadvancedā section in the service provider:
- Check the box āEnable script based conditional authenticationā and paste the following block into the text area :
- Click update on the configuration as well as the service provider page.
All ready except…
The āx-forwarded-forā header is not a default header in HTTP requests. It is only added if the request has been routed through a proxy / load balancer, meaning that the WSO2 Identity server has to be behind a proxy for us to capture the header from the authentication request.
This is common practice in production environments. Therefore, to simulate the header, we need to front the Identity server with a load balancer, which is in our case, Nginx.
- Install Nginx.
- Create a public and private key to be used for Nginx routing:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout <KEY_FILE_PATH> -out <CERTIFICATE_PATH>
- Add the following block to nginx.conf file just before the line āinclude servers/*;ā
- Restart the Nginx server.
- What we are essentially doing here is let Nginx listen on the default WSO2 port while the traffic can be routed to an Identity server with port offset. So, you will also need to increase the port offset = 2 in the IS_HOME/repository/conf/carbon.xml and restart the Identity server.
Ready … Set … Go!!
Now we are ready to try out conditional authentication based on the request IP address!
- Update the āKnown IP Addressā value of āadminā user to be ā10.10.3.12ā from the WSO2 management console.
- Login to the app at āhttp://localhost.com:8080/saml2-web-app-dispatch.com“. You will notice that the login flow includes both basic authentication and the OTP code.
- Update the āKnown IP Addressā value of āadminā user to be ā127.0.0.1ā from the WSO2 management console.
- Login to the app at āhttp://localhost.com:8080/saml2-web-app-dispatch.com“. You will notice that the login flow ends with just basic authentication.
Finishing thoughts
This is a very powerful feature coming with the latest WSO2 Identity server, and we can use various other information from the request headers, user claims, or even user roles to customize the authentication flow at run time.
Happy authenticating!