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:

Certificate_check

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:

1Factor_auth

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:

2Factor_auth

The logical flow of the authentication process is described here:

case_flow

Detailed flow of nFactor authentication for this case

authentication_flow

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

lb_creation

lb_creation1

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

aaa_vserver

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

cert_profile

Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy -> Add

cert_policy

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

ldap_server

Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy -> Add

LDAP_Policy

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

Radius_Server

Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy -> Add

Radius_Policy

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

login_schema_cert_check

Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy Label -> Add

policylabel_cert_check

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

loginschema_2factor

Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy Label -> Add

policylabel_2factor

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

loginschema_noschema

Netscaler -> Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Policy Label -> Add

policylabel_noschema

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

binding

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

ssl_authentication

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

loginschema_bind

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>