During the login flow, you might want to extract which group(s) a user is a member of, and based on that information change the login flow.
In the following example, a user will presented with a username dialog box first, clicks continue, NetScaler will verify that the user exists, do group extraction, and based on the result, present the user with corresponding output
A made up example could be that you want to control how many factors you want to present the user with, based on their group membership.
“Netscaler_1fa” <- only requires 1 factor (in this case password is that factor)
“Netscaler_2fa” <- requires 2 factors, 1st factor is password, 2nd factor is radius
“NetScaler_2fa_native_otp” <- requires 2 factors, 1st factor i password, 2nd factor is build in native OTP on NS.
First, an authentication label that controls the initial user output
1 2 |
add authentication loginSchema ALS_portal_enter_username -authenticationSchema "/nsconfig/loginschema/Portal_enter_user_name.xml" add authentication policylabel AUTHPOLLABEL_enter_user_name -loginSchema ALS_portal_enter_username |
(Portal_enter_user_name.xml is a custom login schema file, which contains one text box that will capture username)
Then create a policy to get the user in the fold: (remember that it is in the binding of a policy that you refer to the authentication label)
1 |
add authentication Policy AUTHPOL_entry -rule "true" -action NO_AUTHN |
Then add the policy to a AAAVS:
1 |
bind authentication vserver AAAVS_portal_entry_v1 -policy AUTHPOL_entry -priority 100 -nextFactor AUTHPOLLABEL_enter_user_name -gotoPriorityExpression END. |
Now the user will be presented with a box to enter the username.
NetScaler needs LDAP servers to verify the username and extract the group. This example will first verify if the user exist, if true, go on to extract the group.
Those policies need to be bound to a new Authentication policy label.
1 2 |
add authentication policylabel AUTHPOLLABEL_int_verify_user_exists -loginSchema LSCHEMA_INT add authentication policylabel AUTHPOLLABEL_int_verify_grp -loginSchema LSCHEMA_INT |
1 2 3 4 5 6 7 8 9 10 |
add authentication ldapAction LDAP-DomainA_noauth -serverIP 1.1.1.10 -ldapBase "dc=domaina,dc=local" -ldapBindDn svc_netscaler_ldap@domaina.local -ldapLoginName userPrincipalName -groupAttrName memberOf -authentication DISABLED add authentication Policy AUTHPOL_DomainA_test_user_exists -rule "AAA.USER.NAME.TO_LOWER.CONTAINS(\"@domaina.com\") -action LDAP-DomainA_noauth add authentication Policy AUTHPOL_2fa_native_otp -rule "AAA.USER.GROUPS.TO_LOWER.CONTAINS(\"netscaler_auth_2fa_native_otp\")" -action NO_AUTHN bind authentication policylabel AUTHPOLLABEL_int_verify_grp -policyName AUTHPOL_2fa_native_otp -priority 80 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_2fa_with_otp_link add authentication Policy AUTHPOL_2fa_grp_ext -rule "AAA.USER.GROUPS.TO_LOWER.CONTAINS(\"netscaler_auth_2fa_ext\")" -action NO_AUTHN bind authentication policylabel AUTHPOLLABEL_int_verify_grp -policyName AUTHPOL_2fa_grp_ext -priority 90 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_2fa add authentication Policy AUTHPOL_1fa -rule "AAA.USER.GROUPS.TO_LOWER.CONTAINS(\"netscaler_auth_1factor\")" -action NO_AUTHN bind authentication policylabel AUTHPOLLABEL_int_verify_grp -policyName AUTHPOL_1fa -priority 100 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_1fa bind authentication policylabel AUTHPOLLABEL_int_verify_user_exists -policyName AUTHPOL_DomainA_test_user_exists -priority 100 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_grp bind authentication policylabel AUTHPOLLABEL_int_verify_user_exists -policyName AUTHPOL_DomainB_test_user_exists -priority 110 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_grp |
To get the users from the initial point(enter user name), there has to be a policy that sends them there(verify ldap user exists), so another “true” policy is needed (and bound) so that the verification and group extraction process starts.
1 2 |
add authentication Policy AUTHPOL_extract_user -rule true -action NO_AUTHN bind authentication policylabel AUTHPOLLABEL_enter_user_name -policyName AUTHPOL_extract_user -priority 100 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_user_exists |
After verification, different passwordboxes needs to be displayed, which are controlled in 3 different Authentication policy labels:
1 2 3 4 5 6 |
add authentication loginSchema ALS_only_password -authenticationSchema "/nsconfig/loginschema/OnlyPassword_new.xml" add authentication policylabel AUTHPOLLABEL_1fa -loginSchema ALS_only_password add authentication loginSchema ALS_2fa_nousername_with_pwreset_link -authenticationSchema "/nsconfig/loginschema/2fa_nousername_with_link.xml" add authentication policylabel AUTHPOLLABEL_2fa -loginSchema ALS_2fa_nousername_with_pwreset_link add authentication loginSchema ALS_Manage_OTP -authenticationSchema "/nsconfig/loginschema/LoginSchema/SingleAuthManageOTP.xml" add authentication policylabel AUTHPOLLABEL_2fa_native_otp -loginSchema ALS_Manage_OTP |
The policy that needs to boud to all of them have to be true, since we are not verifying in the policylabel, but only presenting output to the user, so catching the input from the password boxes and verifying that input in the next authentication policy label.
1 2 3 4 |
add authentication Policy AUTHPOL_NOAUTHN_true -rule true -action NO_AUTHN bind authentication policylabel AUTHPOLLABEL_1fa -policyName AUTHPOL_NOAUTHN_true -priority 100 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_ldap bind authentication policylabel AUTHPOLLABEL_2fa -policyName AUTHPOL_NOAUTHN_true -priority 100 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_radius bind authentication policylabel AUTHPOLLABEL_2fa_native_otp -policyName AUTHPOL_NOAUTHN_true -priority 100 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_otp |
By doing it this way, you’ll end up with fewer policylabels and more policies, and it might seem complex now, but going forward with additional 10 domains, it’s much easier to have “the display flow” set in stone in a few policylabels, and just adding policies to the policy labels, like content switch policies.
The rest of configuration is not explained, but shown so you have a working example.
1 2 3 4 5 6 7 8 9 10 11 12 |
add authentication ldapAction LDAP-DomainA -serverIP 1.1.1.10 -ldapBase "dc=domaina,dc=local" -ldapBindDn svc_netscaler_ldap@domaina.local -ldapLoginName userPrincipalName -groupAttrName memberOf add authentication ldapAction LDAP-DomainB -serverIP 1.1.1.11 -ldapBase "dc=domainb,dc=local" -ldapBindDn svc_netscaler_ldap@domainb.local -ldapLoginName userPrincipalName -groupAttrName memberOf add authentication Policy AUTHPOL_domaina_ldap -rule "AAA.USER.NAME.TO_LOWER.CONTAINS(\"@domaina.com\")" -action LDAP-DomainA add authentication Policy AUTHPOL_domainb_ldap -rule "AAA.USER.NAME.TO_LOWER.CONTAINS(\"@domainb.com\")" -action LDAP-DomainB bind authentication policylabel AUTHPOLLABEL_int_verify_ldap -policyName AUTHPOL_DomainA_ldap -priority 100 -gotoPriorityExpression END bind authentication policylabel AUTHPOLLABEL_int_verify_ldap -policyName AUTHPOL_DomainB_ldap -priority 110 -gotoPriorityExpression END add authentication radiusAction RADIUSSRV_DomainA -serverName DomainA_rad -serverPort 1812 add authentication radiusAction RADIUSSRV_DomainB -serverName DomainB_rad -serverPort 1812 add authentication Policy AUTHPOL_domaina_radius -rule "AAA.USER.NAME.TO_LOWER.CONTAINS(\"@domaina.com\")" -action RADIUSSRV_DomainA bind authentication policylabel AUTHPOLLABEL_int_verify_radius -policyName AUTHPOL_domaina_radius -priority 110 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_ldap add authentication Policy AUTHPOL_domainb_radius -rule "AAA.USER.NAME.TO_LOWER.CONTAINS(\"@domainb.com\")" -action RADIUSSRV_DomainB bind authentication policylabel AUTHPOLLABEL_int_verify_radius -policyName AUTHPOL_domaina_radius -priority 140 -gotoPriorityExpression END -nextFactor AUTHPOLLABEL_int_verify_ldap |
An upcoming article will describe how to make use of native OTP in NetScaler with multiple domains on the same AAAvs, and control it with policies, instead of on vServers.
Happy exploring with n-Factor!
HI, Read your article trying to figure out where are you extracting the user to see if that user exsit in that group. Is it possible to write this article using GUI
Thanks
Hi Farooq, try and paste all the config into your netscaler and check the gui.
Do you guys have a working OTP only schema where the user gets prompted for the passcode after authentication
Hello,
Thank you for sharing the howto.
The command to create AUTHPOLLABEL_2fa_with_otp_link policyLabel should be this ?
add authentication policylabel AUTHPOLLABEL_2fa_with_otp_link -loginSchema LSCHEMA_INT
i see that command is missing.
No, that would create a policylabel thats internally checking something about the procces(could be a groupmembership).
I try to name my policylabels so they give some kind of meaning, and since its “with_otp_link” in the name, i would expect this policylabel to display something to the user in the process. but i cant recall the exact flow. Good luck!