nFactor authentication gives administrators an easy, flexible way to authenticate users, based on different kinds of user access, credentials provided or application demands.
In this post, we are going to describe following common use case for nFactor authentication:
1. The user is accessing authentication vServer.
2. The user is asked to provide the certificate for certificate based authentication as 1st factor. They’ll see a popup window in the browser that asks them to choose a user certificate installed in browser that looks similar to this:
3. The user is authenticated on certificate based the authentication policy configured as 1st factor.
4. If step 3 is successful, then his username is extracted from the certificate and he should provide his password only for 2nd factor as LDAP authentication:
5. If step 3 fails, the user should provide the username/password for LDAP as 1st factor and the passphrase-code for Radius authentication as 2nd factor:
The logical flow of the authentication process is described here:
Detailed flow of nFactor authentication for this case
Configuration steps
Configuration steps are tested in Netscaler Firmware release 11.0-64.
1. Creating load balancing vServer
add lb vserver mail.demoex.local SSL 192.168.100.65 443 -persistenceType NONE -cltTimeout 180 -AuthenticationHost form.demoex.local -Authentication ON -authnVsName form.demoex.local
or via GUI:
Netscaler -> Traffic Management -> Load Balancing -> Virtual Servers -> Add
2. Creating AAA TM Authentication vServer
add authentication vserver form.demoex.local SSL 192.168.100.64 443 -AuthenticationDomain form.demoex.local
or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Virtual Servers -> Add
3. Configuration of advanced certificate authentication policy
add authentication certAction Cert_Auth_Profile -twoFactor ON -userNameField Subject:CN
add authentication Policy CERT-AD-Exch2016 -rule HTTP.REQ.IS_VALID -action Cert_Auth_Profile
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Basic Policies -> CERT -> Profiles -> Add
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy -> Add
4. LDAP authentication policy
add authentication ldapAction DC-Exch2016 -serverIP 10.0.0.36 -ldapBase “DC=demoex,DC=local” -ldapBindDn “CN=Administrator,CN=Users,DC=demoex,DC=local” -ldapBindDnPassword c7c671fc3d36e3d653d7aa67a264639375d65f963ad78d22f5aab05f596673c4 -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName sAMAccountName -groupAttrName memberOf -subAttributeName cn -ssoNameAttribute userPrincipalName
add authentication Policy LDAP-AD-Exch2016 -rule HTTP.REQ.IS_VALID -action DC-Exch2016
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Basic Policies -> LDAP -> Servers -> Add
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy -> Add
5. Radius authentication policy
add authentication radiusAction Radius_NPS_2016 -serverName win2012exch2016.demomuc.local -serverPort 1812 -radKey cb59e3dffcdfef420c045295e7cb0a78598a2b49f1d5b1b6334a84efe12b8c1d -encrypted -encryptmethod ENCMTHD_3 -accounting ON
add authentication Policy NPS-AD-Exch2016 -rule HTTP.REQ.IS_VALID -action Radius_NPS_2016
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Basic Policies -> RADIUS -> Servers -> Add
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy -> Add
6. Login Schema for „Password only“ authentication policy
In this login schema, the user had already provided his certificate and we had extracted his username from this certificate. So we have only one field for password input and his username is been predefined by static expression pointing to username extracted from certificate authentication – „HTTP.REQ.USER.NAME“ .
add authentication loginSchema Cert_Check_1Factor -authenticationSchema login_cert_check_new.xml -userExpression HTTP.REQ.USER.NAME
add authentication policylabel Cert_Check_1Factor -loginSchema Cert_Check_1Factor
bind authentication policylabel Cert_Check_1Factor -policyName LDAP-AD-Exch2016 -priority 100 -gotoPriorityExpression NEXT
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Login Schema -> Profiles -> Add
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy Label -> Add
7. Login Schema for „2 factor authentication“
In this login schema we ask user to provide his username, password and passcode-phrase on one web page. We also notifying user, that his certification authentication has failed.
add authentication loginSchema Cert_Failed_2Factor -authenticationSchema login-2passwd.xml
add authentication policylabel Cert_Failed_2Factor -loginSchema Cert_Failed_2Factor
bind authentication policylabel Cert_Failed_2Factor -policyName LDAP-AD-Exch2016 -priority 100 -gotoPriorityExpression NEXT
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Login Schema -> Profiles -> Add
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy Label -> Add
8. Login Schema „noschema“ for reuse of provided credentials
In this case, we would like to „reuse“ already provided user credentials and not ask user to enter Passcode, etc. So we use built in schema „noschema“ in this case.
add authentication loginSchema Radius_Noschema -authenticationSchema noschema
add authentication policylabel Radius_2Factor_Noschema -loginSchema Radius_Noschema
bind authentication policylabel Radius_2Factor_Noschema -policyName NPS-AD-Exch2016 -priority 100 -gotoPriorityExpression NEXT
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Login Schema -> Profiles -> Add
Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy Label -> Add
9. Binding advanced authentication policies
In this case certification policy will authenticate user and in case of success will use second factor with Policylabel pointing to LDAP authentication. In case of certification policy failure, less priority LDAP authentication will authenticate user, followed by second factor – Radius authentication.
bind authentication vserver form.demoex.local -policy CERT-AD-Exch2016 -priority 100 -nextFactor Cert_Check_1Factor -gotoPriorityExpression NEXT
bind authentication vserver form.demoex.local -policy LDAP-AD-Exch2016 -priority 110 -nextFactor Radius_2Factor_Noschema -gotoPriorityExpression NEXT
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Virtual Servers -> vServer Name -> Edit -> Advanced Authentication Policies
10. Configuration certificate authentication prerequisites
We should enable SSL client authentication with Optional or Mandatory client certificate request to make CERT Authentication works. It is very important to make sure, that the user account is placed in OU in Active Directory. If user account is contained in default class name (“CN=Users”), it could lead to failure in extracting username from provided certificate, despite of successful certificate authentication.
set ssl vserver form.demoex.local -clientAuth ENABLED -clientCert Optional
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Virtual Servers -> vServer Name -> Edit -> SSL Parameters
11. Binding Login Schema to AAA Authentication vServer
In case of successful CERT authentication of the user, policylabel will display „Password only“ input form from „login_cert_check_new.xml“ and this will be the first page, that the user will see after choosing correct user certificate. But in case of CERT authentication failure, we would like to display him authentication page with 2 factor credentials from „login-2passwd.xml“ form. To make it a default authentication page, we bind this login schema to AAA Authentication vServer.
bind authentication vserver form.demoex.local -policy Cert_Failed_2Factor -priority 123 -gotoPriorityExpression END
Or via GUI:
Netscaler -> Security -> AAA – Application Traffic -> Virtual Servers -> vServer Name -> Edit -> Login Schemas -> Add
Using XML logon forms
The great benefit of using nFactor authentication with advanced authentication policies is ability to customize authentication forms. We can provide users with customizable notifications, warning messages or reuse already-provided user credentials by using XML pages. In this case we had used 2 XML pages: „login_cert_check_new.xml“ and „login-2passwd.xml“.
„login_cert_check_new.xml“ – this page is used after certificate authentication and provides user with the following services: notifies him, that authentication was successfull, provides him with extracted username and asks for password input. Here is the used code for this page:
<?xml version=”1.0″ encoding=”UTF-8″?>
<AuthenticateResponse xmlns=”http://citrix.com/authentication/response/1“>
<Status>success</Status>
<Result>more-info</Result>
<StateContext></StateContext>
<AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack>
<CancelPostBack>/Citrix/Authentication/ExplicitForms/CancelAuthenticate</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement>
<Credential>
<Type>none</Type>
</Credential>
<Label>
<Text>Certificate Verification Passed for ${http.req.user.name}, please enter password</Text>
<Type>confirmation</Type>
</Label>
</Requirement>
<Requirement>
<Credential>
<ID>passwd</ID>
<SaveID>ExplicitForms-Password</SaveID>
<Type>password</Type>
</Credential>
<Label>
<Text>Password:</Text>
<Type>plain</Type>
</Label>
<Input>
<Text>
<Secret>true</Secret>
<ReadOnly>false</ReadOnly>
<InitialValue></InitialValue>
<Constraint>.+</Constraint>
</Text>
</Input>
</Requirement>
<Requirement>
<Credential>
<ID>saveCredentials</ID>
<Type>savecredentials</Type>
</Credential>
<Label>
<Text>Remember my password</Text>
<Type>plain</Type>
</Label>
<Input>
<CheckBox>
<InitialValue>false</InitialValue>
</CheckBox>
</Input>
</Requirement>
<Requirement>
<Credential>
<ID>loginBtn</ID>
<Type>none</Type>
</Credential>
<Label>
<Type>none</Type>
</Label>
<Input>
<Button>Log On</Button>
</Input>
</Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>
„login-2passwd.xml“ – this page is used in case certificate authentication failure and provides user with 2 services: notifies him, that certificate authentication was not successfull, provides him with the form of username, password and passcode input. Password is stored in variable „passwd“ and used for first factor LDAP authentication. Passcode is stored in variable „passwd1“, that is by default used for second factor with noschema login schema and radius authentication. Here is the used code for this page:
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<AuthenticateResponse xmlns=”https://form.demoex.local/authentication/response/1“>
<Status>success</Status>
<Result>more-info</Result>
<StateContext></StateContext>
<AuthenticationRequirements>
<PostBack>/p/u/doAuthentication.do</PostBack>
<CancelPostBack>/p/u/doLogoff.do</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement>
<Credential>
<Type>none</Type>
</Credential>
<Label>
<Text>Please log on</Text>
<Type>heading</Type>
</Label>
<Input/>
</Requirement>
<Requirement>
<Credential>
<ID>login</ID>
<SaveID>login</SaveID>
<Type>username</Type>
</Credential>
<Label>
<Text>User name:</Text>
<Type>plain</Type>
</Label>
<Input>
<Text>
<ReadOnly>false</ReadOnly>
<InitialValue>${http.req.user.login_name}</InitialValue>
<Constraint>.+</Constraint>
</Text>
</Input>
</Requirement>
<Requirement>
<Credential>
<ID>passwd</ID>
<SaveID>passwd</SaveID>
<Type>password</Type>
</Credential>
<Label>
<Text>Password:</Text>
<Type>plain</Type>
</Label>
<Input>
<Text>
<Secret>true</Secret>
<InitialValue>${http.req.user.passwd}</InitialValue>
<Constraint>.+</Constraint>
</Text>
</Input>
</Requirement>
<Requirement>
<Credential>
<ID>passwd1</ID>
<SaveID>passwd1</SaveID>
<Type>password</Type>
</Credential>
<Label>
<Text>Passcode:</Text>
<Type>plain</Type>
</Label>
<Input>
<Text>
<Secret>true</Secret>
<Constraint>.+</Constraint>
</Text>
</Input>
</Requirement>
<Requirement>
<Credential>
<Type>none</Type>
</Credential>
<Label>
<Text>Certificate Verification Failed, please enter Password and Passcode</Text>
<Type>warning</Type>
</Label>
</Requirement>
<Requirement>
<Credential>
<ID>savecredentials</ID>
<SaveID>
</SaveID>
<Type>savecredentials</Type>
</Credential>
<Label>
<Text>Remember my credentials</Text>
<Type>plain</Type>
</Label>
<Input><AssistiveText>
</AssistiveText>
<CheckBox>
<InitialValue>false</InitialValue>
</CheckBox>
</Input>
</Requirement>
<Requirement>
<Credential>
<ID>Logon</ID>
<Type>none</Type>
</Credential>
<Label>
<Type>none</Type>
</Label>
<Input>
<Button>Submit</Button>
</Input>
</Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>