Native One Time Passwords (OTP) – NetScaler Gateway 12 / Citrix Gateway 12.1

Last Modified: Feb 28, 2019 @ 1:09 pm

Navigation

Change Log

Overview

NetScaler 12 Native OTP lets you enable two-factor authentication without purchasing any other authentication product. A typical configuration uses Google Authenticator to generate Passcodes. See the following for an overview:

Here are some notes:

  • NetScaler Native OTP is part of nFactor, and thus requires Citrix ADC Advanced Edition (aka NetScaler Enterprise Edition) or Citrix ADC Premium Edition (aka NetScaler Platinum Edition) licensing. NetScaler ADC Standard Edition licensing is not sufficient.
  • Workspace app 1809 and newer with Citrix Gateway (NetScaler) 12.1 build 49 and newer support nFactor authentication. Older Receivers and older NetScalers don’t support it, so you’ll instead have to use a web browser.  💡
  • Citrix Gateway VPN Plug-in 12.1 build 49 and later support nFactor when authenticating using the VPN Plug-in.  💡
  • nFactor requires a AAA vServer, which can be non-addressable – you don’t need any additional public IPs.
  • OTP stores device enrollment secrets in an Active Directory attribute that accepts Strings. Citrix’s documentation uses the userParameters Active Directory attribute.
    • The LDAP bind account must have permission to modify this attribute on every user.
  • Users can enroll multiple devices. There’s no way to prevent this.
  • The manageotp website is usually only protected by single factor authentication. Since users can add multiple devices, the manageotp website must be protected from external access.
  • Christian in the comments indicated that Microsoft Authenticator also works. Click on plus sign -> other (Google,…).

Here are the OTP configuration objects:

  • Make sure NTP is configured on the NetScaler. Accurate time is required.
  • An LDAP Policy/Server with authentication disabled and OTP Secret configured. This one OTP-specific LDAP Policy/Server can be used for two scenarios:
    • manageotp device enrollment
    • Two-factor authentication to NetScaler Gateway after a device has been enrolled. This LDAP Policy/Server verifies the entered passcode.
  • An LDAP Policy/Server with authentication enabled. This one policy is used for two scenarios:
    • Single-factor authentication to the manageotp authenticator/device enrollment website.
    • Two-factor authentication to NetScaler Gateway after a device has been enrolled.
  • A single non-addressable AAA vServer with two Login Schemas for the following scenarios:
    • A single-factor Login Schema for manageotp.
    • A dual-factor Login Schema for NetScaler Gateway authentication.
  • An Authentication Profile to link the AAA vServer to the NetScaler Gateway vServer.

LDAP Policies/Actions

  1. Go to Security > AAA – Application Traffic > Polices > Authentication > Advanced Policies > Actions > LDAP.
  2. On the right, click Add.

    1. Create a normal LDAP Server if you don’t have one already. This one has Authentication enabled. This LDAP Policy/Server will be used for single-factor authentication to the manageotp website, and for first factor of dual-factor authentication to NetScaler Gateway (second factor is OTP). There are no special instructions for this LDAP Server.
  3. Create another LDAP Action.

    1. This one is used by the manageotp site to set the OTP authenticator in Active Directory, so name it accordingly.
    2. On the right, uncheck the box next to Authentication. If you don’t uncheck it, you will see an error message after configuring the OTP Secret.
    3. Make sure the Administrator Bind DN has permissions to modify the OTP Secret Active Directory attribute for all users.
    4. If you cloned an existing LDAP Server, then make sure you re-enter the Administrator Password or the new one won’t work. Then click Test LDAP Reachability.
    5. Configure the Server Logon Name Attribute to match the one you configured in the normal authentication LDAP Server.
    6. In the Other Settings section, on the bottom right, find the OTP Secret field. Enter the name of the Active Directory attribute where NetScaler will store the user’s OTP secret. You can use the userParameters attribute if that attribute isn’t being used for anything else.
    7. Thomas Rolfs in the comments advises not to enable Nested Group Extraction in this LDAP Action.
    8. Click Create when done.
  4. Create another LDAP Action.
    1. This one will verify the OTP code entered by the user, so name it accordingly. The only difference from the prior one is the addition of an LDAP Search Filter.
    2. On the right, uncheck the box next to Authentication. If you don’t uncheck it, you will see an error message after configuring the OTP Secret.
    3. Make sure the Administrator Bind DN has permissions to read the OTP Secret Active Directory attribute.
    4. If you cloned an existing LDAP Server, then make sure you re-enter the Administrator Password or the new one won’t work.
    5. In the Other Settings section, configure the Server Logon Name Attribute to match the one you configured in the normal authentication LDAP Server.
    6. In the Search Filter field, enter the text userParameters>=#@. This syntax ensures that only users with enrolled authenticators can login. See George Spiers NetScaler native OTP for more info.
    7. In the Other Settings section, on the bottom right, find the OTP Secret field. Enter the name of the Active Directory attribute containing the user’s OTP secret.
    8. Click Create when done.
  5. Go to Security > AAA – Application Traffic > Policies > Authentication > Advanced Policies > Policy.
  6. On the right, click Add.

    1. You probably don’t already have an Advanced Authentication Policy for your normal LDAP server.
    2. Change the Action Type to LDAP.
    3. Select your normal LDAP server, which is the one that has Authentication enabled.
    4. Enter true as the expression. This uses Default Syntax instead of Classic Syntax.
    5. Click Create.
  7. Create another Authentication Policy.

    1. This policy is for OTP management so name it accordingly.
    2. Change the Action Type to LDAP.
    3. Select the Set OTP LDAP Server that has Authentication disabled and OTP Secret configured. This LDAP Action should not have the Search Filter configured.
    4. Enter HTTP.REQ.COOKIE.VALUE(“NSC_TASS”).EQ(“manageotp”) in the Expression box, and click Create.
  8. Create another Authentication Policy.

    1. This policy is for OTP verification so name it accordingly.
    2. Change the Action Type to LDAP.
    3. Select the OTP Verification LDAP Server that has Authentication disabled and OTP Secret configured. This LDAP Action should have the Search Filter configured to prevent unenrolled users from authenticating.
    4. Enter true in the Expression box, and click Create.

Login Schemas

  1. Go to Security > AAA – Application Traffic > Login Schema.
  2. On the right, switch to the Profiles tab, and click Add.

    1. This is the single factor Login Schema for manageotp so name the Schema accordingly.
    2. Click the Edit icon.
    3. On the left, click the LoginSchema folder to open it.
    4. Scroll down, and click SingleAuthManageOTP.xml to highlight it.
    5. On the top right, click Select.
    6. Click Create.
  3. Add another Login Schema profile.

    1. This Login Schema is for two-factor authentication to NetScaler Gateway so name it accordingly.
    2. Click the edit icon. Follow the same procedure as above, but this time select /LoginSchema/DualAuth.xml.
    3. Click More to reveal more options.
    4. Scroll down. In the Password Credential Index field, enter 1. This causes nFactor to save the user’s password into AAA Attribute #1, which we’ll use later in a Traffic Policy to Single Sign-on to StoreFront. If you don’t do this, then NetScaler Gateway will try to use the Passcode to authenticate to StoreFront, which obviously won’t work.
    5. Check the box next to Enable Single Sign On Credentials. Mark in the comments indicates that this checkbox is needed to Single Sign On to RDP Hosts.
    6. Click Create.
  4. On the right, switch to the Policies tab.
  5. Click Add to add a Login Schema policy.
    1. In the Profile field, select the Single Factor Manage OTP Login Schema Profile.
    2. Name the Login Schema Policy for OTP management.
    3. In the Rule field, enter the following. This ensures that this single factor Login Schema is only used if the user enters /manageotp, and if the user is on the internal network. You don’t want manageotp to be accessible externally, because it’s only protected by single factor authentication, and it’s too easy to add multiple devices.
      http.req.cookie.value("NSC_TASS").eq("manageotp") && client.IP.SRC.IN_SUBNET(10.2.0.0/16)
    4. Click Create.
  6. Create another Login Schema Policy.

    1. In the Profile field, select the dual factor Login Schema.
    2. Name the Login Schema to indicate dual factor authentication.
    3. In the Rule box, enter true.
    4. Click Create.

Authentication PolicyLabel

  1. Go to Security > AAA – Application Traffic > Policies > Authentication > Advanced Policies > PolicyLabel.
  2. On the right, click Add.
  3. This PolicyLabel is for OTP management, and OTP verification, so name it accordingly.
  4. In the Login Schema field, select LSCHEMA_INT, which means noschema.
  5. Click Continue.
  6. In the Policy Binding section, Click to select.
  7. Click the radio button button next to the Manage OTP LDAP Policy that has authentication disabled, and OTP Secret configured. This one should have a policy expression that limits it to manageotp only. Click Select.
  8. Click Bind.
  9. Click Add Binding to add another one.
  10. Click to select.
  11. Click the radio button next to the LDAP Policy that verifies OTP. Click Select.
  12. Click Bind.
  13. Make sure the manageotp policy is higher in the list than the OTP Verification policy. To adjust priorities, right-click on the policies, and click Edit Binding. Click Done.

AAA vServer

  1. Go to Security > AAA – Application Traffic.
    1. If the AAA feature is not enabled, then right-click the AAA node, and click Enable Feature.
  2. Go to Security > AAA – Application Traffic > Virtual Servers.
  3. On the right, click Add.
  4. This AAA vServer is for OTP so name it accordingly.
  5. Change the IP Address Type to Non Addressable.
  6. Click OK.
  7. Click where it says No Server Certificate.

    1. In the Server Certificate Binding section, click Click to select.
    2. Click the radio button next to a certificate, and click Select. You can use the same certificate as NetScaler Gateway.
    3. Click Bind.
  8. Click Continue to close the Certificate section.
  9. In the Advanced Authentication Policies section, click where it says No Authentication Policy.

    1. Click where it says Click to select.
    2. Click the radio button next to the normal LDAP Policy that has authentication enabled. Then click the blue Select button.
    3. In the Select Next Factor field, click where it says Click to select.
    4. Click the radio button next to the OTP PolicyLabel, and click Select.
    5. Click Bind.
  10. In the Advanced Authentication Policies section, click Continue.
  11. On the right, in the Advanced Settings column, click Login Schemas.
  12. On the left, scroll down, and click where it says No Login Schema.

    1. Click where it says Click to select.
    2. Click the radio button next to the Manage OTP Login Schema, and click Select.
    3. Click Bind.
  13. Click where it says 1 Login Schema.

    1. Click Add Binding.
    2. Click where it says Click to select.
    3. Click the radio button next to the dual factor Login Schema, and click Select.
    4. Click Bind.
    5. Make sure the single factor Manage OTP Login Schema is higher in the list (lower priority number) than the dual factor Login Schema. Click Close.
  14. On the right, in the Advanced Settings column, click Portal Themes.
  15. On the left, scroll down, select RfWebUI as the Portal Theme, and click OK.
  16. Click Done.

Traffic Policy for Single Sign-on

  1. On the left, go to NetScaler Gateway > Policies > Traffic.
  2. On the right, switch to the Traffic Profiles tab, and click Add.
  3. This Traffic Profile is for OTP and/or nFactor. Name it accordingly.
  4. Scroll down.
  5. In the SSO Password Expression box, enter the following. This is where we use the Login Schema Password Attribute specified earlier.
    http.REQ.USER.ATTRIBUTE(1)
  6. Click Create.
  7. On the right, switch to the Traffic Policies tab, and click Add.
  8. In the Request Profile field, select the Traffic Profile you just created.
  9. Name the Traffic Policy.
  10. In the Expression box, enter true (Default Syntax).
    • If your NetScaler Gateway Virtual Server allows full VPN, change the expression to the following. Source = Julien Mooren at NetScaler – Native OTP is breaking SSL VPN.
      http.req.method.eq(post)||http.req.method.eq(get) && false
  11. Click Create.

NetScaler Gateway and Authentication Profile

  1. Go to NetScaler Gateway > Virtual Servers.
  2. Edit an existing Gateway vServer. If you don’t have one, see the other NetScaler Gateway topics on this site.
  3. Scroll down to the Policies section, and click the plus icon.
  4. Change the Choose Policy drop-down to Traffic, and click Continue.
  5. Click to select.
  6. Click the radio button next to the Traffic Policy you created earlier, and click Select.
  7. Click Bind.
  8. On the right, in the Advanced Settings column, click Authentication Profile.
  9. On the left, scroll down to the Authentication Profile section.
  10. Click Add to create one.
  11. Authentication Profile links the NetScaler Gateway vServer with the OTP AAA vServer, so name it accordingly.
  12. In the Authentication Virtual Server section, Click to select.
  13. Click the radio button next to the OTP AAA vServer, and click Select.
  14. Click Create.
  15. Scroll down again to the Authentication Profile section, and click OK.
  16. The Portal Theme bound to the Gateway vServer should be RfWebUI, or a derivative.
  17. Go to System > Profiles.
  18. On the right, switch to the SSL Profile tab.
  19. Edit the ns_default_ssl_profile_frontend profile.
  20. Make sure HSTS is not enabled in the profile, or RfWebUI, and manageotp won’t work correctly. This is probably a bug. Note: the Rewrite method of enabling HSTS should work.

Update Content Switching Expression for Unified Gateway

If your NetScaler Gateway Virtual Server is behind a Unified Gateway (Content Switching Virtual Server), then you must update the Content Switching Expression to include the manageotp paths.

  1. In the NetScaler GUI, navigate to ConfigurationTraffic Management > Content Switching > Policies.
  2. On the right, select the Unified Gateway Content Switching Policy, and then click Edit.
  3. Append the following expression under the Expression area, and then click OK.
    || HTTP.REQ.URL.CONTAINS("/manageotp")

Manageotp

  1. Point your browser to https://mygateway.corp.com/manageotp or similar. Simply add /manageotp to the end of your Gateway URL.
  2. Notice it’s only single-factor authentication. Login using normal LDAP credentials.
  3. Click Add Device.
  4. Enter a device name, and click Go.
  5. Launch the Google Authenticator application on your phone. Click the plus icon in Google Authenticator, and scan the QRCode that is shown on the screen.
  6. Christian in the comments indicated that Microsoft Authenticator also works. Click on plus sign -> other (Google,…).
  7. Click Test.
  8. Enter the passcode shown in your Authenticator, and click Go.
  9. If you logoff of manageotp, and access your Gateway URL normally, you’ll be prompted for two-factor authentication. Use the passcodes shown in your Google Authenticator application.
  10. It should Single Sign-on into StoreFront.

CLI Commands

Here’s a complete CLI configuration.

add ssl certKey WildcardCorpCom -cert WildcardCorpCom.pfx -key WildcardCorpCom.pfx -inform PFX -passcrypt "abc"
add authentication ldapAction LDAP-Corp -serverIP 10.2.2.11 -serverPort 636 -ldapBase "dc=corp,dc=local" -ldapBindDn ctxsvc@corp.local -ldapBindDnPassword abc -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName sAMAccountName -groupAttrName memberOf -subAttributeName cn -secType SSL -passwdChange ENABLED -Attribute2 userParameters
add authentication ldapAction LDAP_OTP_set_no_auth -serverIP 10.2.2.11 -serverPort 636 -ldapBase "dc=corp,dc=local" -ldapBindDn admin@corp.local -ldapBindDnPassword abc -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName sAMAccountName -groupAttrName memberOf -subAttributeName cn -secType SSL -authentication DISABLED -OTPSecret UserParameters
add authentication ldapAction LDAP_OTP_verify_no_auth -serverIP 10.2.2.11 -serverPort 636 -ldapBase "dc=corp,dc=local" -ldapBindDn admin@corp.local -ldapBindDnPassword abc -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName sAMAccountName -searchFilter "userParameters>=#@" -groupAttrName memberOf -subAttributeName cn -secType SSL -authentication DISABLED -OTPSecret UserParameters
add authentication Policy Corp-Adv -rule true -action LDAP-Corp
add authentication Policy LDAP_Manage_OTP-pol -rule "HTTP.REQ.COOKIE.VALUE(\"NSC_TASS\").EQ(\"manageotp\")" -action LDAP_OTP_set_no_auth
add authentication Policy LDAP_Confirm_OTP-pol -rule true -action LDAP_OTP_verify_no_auth

add authentication loginSchema Dual_OTP-lschema -authenticationSchema "/nsconfig/loginschema/LoginSchema/DualAuth.xml" -passwordCredentialIndex 1
add authentication loginSchema Single_Manage_OTP-lschema -authenticationSchema "/nsconfig/loginschema/LoginSchema/SingleAuthManageOTP.xml"
add authentication loginSchemaPolicy Single_Manage_OTP-lschemapol -rule "http.req.cookie.value(\"NSC_TASS\").eq(\"manageotp\") && client.IP.SRC.IN_SUBNET(10.3.0.0/16)" -action Single_Manage_OTP-lschema
add authentication loginSchemaPolicy Dual_OTP-lschemapol -rule true -action Dual_OTP-lschema

add authentication policylabel OTP_pollabel -loginSchema LSCHEMA_INT
bind authentication policylabel OTP_pollabel -policyName LDAP_Manage_OTP-pol -priority 100 -gotoPriorityExpression NEXT
bind authentication policylabel OTP_pollabel -policyName LDAP_Confirm_OTP-pol -priority 110 -gotoPriorityExpression NEXT 

add authentication vserver OTP-AAA SSL 0.0.0.0
bind ssl vserver OTP-AAA -certkeyName WildcardCorpCom

bind authentication vserver OTP-AAA -portaltheme RfWebUI
bind authentication vserver OTP-AAA -policy Single_Manage_OTP-lschemapol -priority 100 -gotoPriorityExpression END
bind authentication vserver OTP-AAA -policy Dual_OTP-lschemapol -priority 110 -gotoPriorityExpression END
bind authentication vserver OTP-AAA -policy Corp-Adv -priority 100 -nextFactor OTP_pollabel -gotoPriorityExpression NEXT

add vpn trafficAction OTP-trafficprofile http -passwdExpression "http.REQ.USER.ATTRIBUTE(1)"
add vpn trafficPolicy OTP-trafficpol true OTP-trafficprofile

add authentication authnProfile OTP-authnprofile -authnVsName OTP-AAA

add vpn vserver Gateway.corp.com SSL 10.2.5.220 443 -downStateFlush DISABLED -Listenpolicy NONE -authnProfile OTP-authnprofile
set ssl vserver Gateway.corp.com -sslProfile ns_default_ssl_profile_frontend
add vpn sessionAction "Receiver For Web" -transparentInterception OFF -defaultAuthorizationAction ALLOW -SSO ON -icaProxy ON -wihome "https://storefront2.corp.com/Citrix/StoreWeb" -ntDomain corp.local -clientlessVpnMode OFF -storefronturl "https://storefront2.corp.com"
add vpn sessionPolicy "Receiver For Web" "HTTP.REQ.HEADER(\"User-Agent\").CONTAINS(\"CitrixReceiver\").NOT" "Receiver For Web"
bind vpn vserver Gateway.corp.com -portaltheme RfWebUI
bind vpn vserver Gateway.corp.com -policy "Receiver For Web" -priority 100 -gotoPriorityExpression NEXT -type REQUEST
bind vpn vserver Gateway.corp.com -policy OTP-trafficpol -priority 100 -gotoPriorityExpression END -type REQUEST
bind ssl vserver Gateway.corp.com -certkeyName WildcardCorpCom

310 thoughts on “Native One Time Passwords (OTP) – NetScaler Gateway 12 / Citrix Gateway 12.1”

  1. Hi Carl,

    Our company is mostly working from home, unfortunately making the /manageotp website accessible internally doesn’t work well for new users. Do you have any suggestions?

    1. Hi Mohammed,

      Admin can generate a key code and share it to user and don’t forget to add the same code in AD user parameter against each user

  2. Anyone having issue which when you key in the old One time password when a new otp is available you can successfully login?

  3. Hello Carl,

    Amazing article, thanks for sharing. I used and worked as expected for Web Browsers cenario.

    When I tried to use with Workspace App 1909 the login page don´t load.

    Do you have any advice for this behavior ?

  4. Great instructions Carl, Thank you so much!
    I set this up on our ADC but one client does not want to use an app.
    Do you by chance have an article\how to that would use Nfactor and be able to send a pass code to the users email address?
    I have searched and can not find anything.

    1. I haven’t found a way to do that yet. SSPR supports email but I haven’t seen it used anywhere else.

  5. Hi Carl!

    What about if I want to separate my second factor on a new schema with only OTP password field? I have tried it but when I must to comparate OTP password introduced by user, it doesnt work.

    Any idea?

  6. Hi,
    Thanks for your article. Is it possible to send an email to users when a device is added to /manageotp portal?

  7. Hi Carl

    Thank you for the detailed steps and it working perfectly. but am struck when i try to improvise according to my requirement.

    am trying to add client cert in addition to this…

    Client cert -> Ldap -> Native otp with username to be fetched from the client cert. I did modification on the both singleauth and dualauth.xml but it is not fetching the username from certificate. Any idea and thought would be helpful

  8. Hi Carl,

    Thanks a lot for this detailed procedure. I have followed the procedure and reviewed it twice but something is missing. The version is 12.1 55.24. When I browse to the https://mgmtip/manageotp I receive the message “The requested page was not found on this server.”.
    When I browse to the https://gateway address I get the correct page with the password and passcode.
    I double-checked for typo’s with the manageotp strings but couldn’t find anything. Is there something else which could be the reason? Thanks for your help!

  9. Hi Carl, loving this very detailed tutorial which we also tried to apply.
    Went through all carefully and installed a 2nd Netscaler Gateway beneath an existing one which “OTPs” agains censornet sms passcode.
    But we already struggle when trying to enroll a device as it´s giving us “invalid credentials” at the 1factor auth login, nevertheless if we try with a default domain user or with a domain admin user account.

    Tried to get a clue out of the aaad.debug but wasn´t successful until here, hoping to get some more insight now.
    See below the logged lines with the error.

    Thanks in advance for any help.
    Regards Oliver

    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[696]: main 0-0: timer 2 firing…
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[901]: process_kernel_socket 0-313: partition id is 0
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[1123]: process_kernel_socket 0-313: ns_aaad_decrypt_auth not done
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[1163]: process_kernel_socket 0-313: call to authenticate
    user :USERNAME, vsid :14540, userlen 8
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[1222]: process_kernel_socket 0-313: call to authenticate
    user :USERNAME, vsid :14540, req_flags 2
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5310]: start_cascade_auth 0-313: starting cascade authentication
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5423]: cascade_auth 0-313: starting ldap auth for: USERNAME, sizeof(*ar) is 36, userlen 9
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[121]: start_ldap_auth 0-313: Starting LDAP auth
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[145]: start_ldap_auth 0-313: attempting to do ldap auth for USERNAME @ 192.168.200.111
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[147]: start_ldap_auth 0-313: LDAP referrals are OFF
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[148]: start_ldap_auth 0-313: LDAP referral nesting depth 0
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[976]: continue_ldap_init 0-313: Connecting to: 192.168.200.111:636
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[982]: continue_ldap_init 0-313: User USERNAME Connecting to: 192.168.200.111:636
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5662]: register_timer 0-313: setting timer 605
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5739]: unregister_timer 0-313: releasing timer 605
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1056]: ns_ldap_set_up_socket 0-313: Server certificate hostname = NULL
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1066]: ns_ldap_set_up_socket 0-313: Setting timeouts for SSL/TLS.
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1103]: ns_ldap_set_up_socket 0-313: Set cert verify level 0
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1106]: ns_ldap_set_up_socket 0-313: Getting cipher suite global value
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1109]: ns_ldap_set_up_socket 0-313: Checking non-zero cipher suite
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1119]: ns_ldap_set_up_socket 0-313: NULL cipher suite. Using default.
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1125]: ns_ldap_set_up_socket 0-313: Freeing cipher suite value
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1132]: ns_ldap_set_up_socket 0-313: Done with cipher suite
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1164]: ns_ldap_set_up_socket 0-313: setting up for SSL connection to : 192.168.200.111:636
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1210]: ns_ldap_set_up_socket 0-313: Successfully established connection to NULL
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5662]: register_timer 0-313: setting timer 606
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[201]: receive_ldap_bind_event 0-313: receive ldap bind event

    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[463]: ns_ldap_check_result 0-313: checking LDAP result. Expecting 97 (LDAP_RES_BIND)
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[467]: ns_ldap_check_result 0-313: Got result 0. Non-event, continuing
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[226]: receive_ldap_bind_event 0-313: Noop
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[201]: receive_ldap_bind_event 0-313: receive ldap bind event

    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[463]: ns_ldap_check_result 0-313: checking LDAP result. Expecting 97 (LDAP_RES_BIND)
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[467]: ns_ldap_check_result 0-313: Got result 0. Non-event, continuing
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[226]: receive_ldap_bind_event 0-313: Noop
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[201]: receive_ldap_bind_event 0-313: receive ldap bind event

    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[463]: ns_ldap_check_result 0-313: checking LDAP result. Expecting 97 (LDAP_RES_BIND)
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[501]: ns_ldap_check_result 0-313: ldap_result found expected result LDAP_RES_BIND
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[213]: receive_ldap_bind_event 0-313: Bind OK
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5739]: unregister_timer 0-313: releasing timer 606
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[282]: receive_ldap_bind_event 0-313: Original slen: 8
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[306]: receive_ldap_bind_event 0-313: User name: dirty = sanitized =
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[308]: receive_ldap_bind_event 0-313: Admin bind successful, attempting user search event for USERNAME
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[2458]: get_email_attribute 0-313: Email attribute: , length 5
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1396]: ns_ldap_search 0-313: Searching for <> from base <>
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5662]: register_timer 0-313: setting timer 607
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[1420]: ns_ldap_search 0-313: Sent user search query.
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[407]: receive_ldap_user_search_event 0-313: Received LDAP user search event.
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[463]: ns_ldap_check_result 0-313: checking LDAP result. Expecting 101 (LDAP_RES_SEARCH_RESULT)
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[501]: ns_ldap_check_result 0-313: ldap_result found expected result LDAP_RES_SEARCH_RESULT
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[325]: ns_show_ldap_err_string 0-313: LDAP error string: <>
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[511]: ns_ldap_check_result 0-313: LDAP action failed (error 1): Operations error
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_common.c[513]: ns_ldap_check_result 0-313: For user USERNAME, LDAP authentication failed (error 1): Operations error
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[441]: receive_ldap_user_search_event 0-313: LDAP user search event failed for user USERNAME
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[5739]: unregister_timer 0-313: releasing timer 607
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[4781]: send_reject_with_code 0-313: Not trying cascade again 4001
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[4783]: send_reject_with_code 0-313: sending reject to kernel for : USERNAME
    Tue Mar 17 14:51:29 2020
    /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[4801]: send_reject_with_code 0-313: Rejecting with error code 4001

    1. I see “LDAP user search event failed for user USERNAME”

      Is your LDAP Policy/Server configured with a LDAP Search Filter? Or are you entering a username that doesn’t exist in LDAP? Or is your LDAP Policy/Server configured for userPrincipalName but you’re only entering samAccountName?

      1. Got a bit further since (existing) standard LDAP connector did not show a password. After retyping it, this issue is solved, devices can be registered.
        But now I have new stuff:
        1) STA servers in new Gateway are presented down although they work fine in the other Gateway
        2) After logging in with 2factor, it´s presenting me again a single factor login (…to Storefront Website).

        Is 2) a direct cause of 1)?
        Can I use STA servers in parallel with more than one Citrix Gateway?

        Thanks a lot for help..
        Oliver

        1. STA servers might be a bug. Note: the STA monitor only checks every two minutes. I sometimes have to remove all STAs and re-add them for them to show up.

          Check StoreFront Server > Event Viewer > Applications and Services > Citrix Delivery Services.

          1. After re-adding STAs and 2nd and 3rd time, this is also fine right now.
            So last thing is currently the 2nd 1factor login screen after 2factor login instead of forwarding to Published Apps etc.
            Where can I troubleshoot this?

          2. Again went a bit further.
            At the Storefront Store I had to add new public URL in “Remote Access Settings” to be accepted by SF as in parallel to existing ADC Gateway.
            Now, after logging in with 2factor, it´s showing “Request can not be completed”

            AAAD.debug is showing this:
            Fri Mar 20 10:03:04 2020
            /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/ldap_drv.c[905]: receive_ldap_user_search_event 2-956: Authentication is disabled for user USERNAME, finishing ldap authentication
            Fri Mar 20 10:03:04 2020
            /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[3923]: send_accept 2-956: sending accept to kernel for : USERNAME
            Fri Mar 20 10:03:04 2020
            /home/build/rs_121_55_4_RTM/usr.src/netscaler/aaad/naaad.c[3840]: aaad_alloc_serialize_keyValue_attrs 2-956: Total attribute values to PE : 63, email=username@domain.com

            Don´t know where having to control authentication for a user as in your guide there´s nothing about e.g. a group membership to grant access.

            Any help would be highly appreciated.

    2. Remove this expression and enter again manually. it will solve login issue in single factor authentication.
      You need to select VAULE(STRING). If you copy paste it will take “VALUE(UNIT). SO WILL NOT ABLE TO LOGIN ON \manageotp portal.

  10. Followed the guide and its not working,
    aaad_json_read_otp_attribute_value 1-2940: Failed to bas64 deocde OTP data, processing it as plain text
    unsigned int aaad_base64decode(char*, unsigned int, char*, unsigned int) 1-2940: [POCO]Base64 Decode: Failed to decode string..
    void* json_get_parser(char*) 1-2940: [POCO]JSON: JSON for parsing failed …

  11. Hi carl,
    once mobile register for otp, there is any possibility to change the registered mobile.
    Because if hacker has user name password he easily get login with registered his own mobile.
    ?

  12. Hi Carl,

    I have the same problem that Simon Magee June 4, 2019 at 11:17 am

    I can’t create the ‘Dual_OTP-lschema’ within my AAA Schema Profiles, but I keep getting an error ‘Content type doesn’t match the resource name’

    Could you help me ? I’m in version 13.0 47.22

    1. Hmm, I just created a new Login Schema Profile in 13.0 47.22 with the DualAuth.xml file and no error. Did you clear your browser cache after upgrading to 47.22? Are you using Chrome?

      1. i have create without the 1 parameter, ok, i edit and place the 1 … ok … so i think it’s ok now for this parameter.
        I have follow all the instruction and i have the good splash screen with the secret code. In local, i try to connect to the /manage otp, i try to send login and password, and he say, please contact assistant service.

      2. Ok carl. I have try to create without the 1 parameter, and it’s ok. I edit it, and add the 1 parameter and now i can save it …

        I have in extern network the secret box now. If i try to go to manageotp from Inside network, i have the splash screen. I try to authenticate and … error. Must to contact assistant.

  13. Hi Carl,

    Good Day!!

    I have configured the Netscaler settings & everything is working fine using OTP feature.

    Netscaler version # NS12.1 51.19.nc

    I observed that few users does not register themselves on ManageOTP url.

    Can you please suggest, how can I force users to register the device first & then login to Storefront page.

    Awaiting your reply.

    Thanks,
    Harsh Kumar

    1. In the LDAP Search Filter field, enter the text userParameters>=#@. This syntax ensures that only users with enrolled authenticators can login.

      1. Hi Carl,

        LDAP Search Filter field is already have the same settings.

        But what I want to do is that when user open the URL for the first time, it should redirect to manageotp url to register the device.

        However, in current scenerio, user enter’s the username & password & able to login if they did not register the device.

        1 more update, I have configured the OTP settings using the article “https://www.irangers.com/netscaler-native-otp-limit-enrollment-one-device”.

        Thanks,
        Harsh Kumar

        1. I have a same problem.I think you just need to change the schema to DualAuthOrOTPRegisterDynamic.xml instead of DualAuth.xml,it may be easier.

      2. Does it’s possible to protect acces of the /manageotp for people who are member of specific ad group?
        How can i impersonate the creation of device for user ? I would like to create device for user and send the passkey / wrcode with sms / mail … other solution ?

  14. Hi Carl,Thanks for the article!

    I am having issue with doing OTP from a Single Gateway VIP for multiple domains .I tried the Domain drop down for first factor and then second factor the OTP but it only works for one domain since I cannot get a expression that will distinguish between the domains for the OTP registration as well as login .Also the credentials does not get passed through correctly and I am asked to authentication at the Storefront again .We are using domain/username with SAMAacount name for domain and any domain on the Storefront server .I also have issue with the Session policies for the different domains to determine which is which via expression .

    We are trying to accomplish the following

    4 domains to register OTP and authenticate with on a Single gateway VIP using Nfactor .
    Storefront is set to allow any domain
    NetScaler LDAP Profile need to use SAMAacount details .
    Login to Gateway must use domain/user

    Any easier recommendations would be much helpful !

  15. Hi Carl,

    i have a problem with before the registration of the Device.
    When i access the URL of the Gateway vServer with /manageotp i get the Logon page with one Factor. Aftern typing in the credentials i get an notification: “Please Contact support”

    In the nsconmsg command i see the following table:

    Displaying current counter value information
    NetScaler V20 Performance Data
    NetScaler NS12.0: Build 60.10.nc, Date: Jan 10 2019, 01:24:17

    reltime:mili second between two records Tue Sep 10 15:56:26 2019
    Index reltime counter-value symbol-name&device-no
    1 1526054 1 mem_tot_slotpages_allocated
    3 0 0 mem_tot_slotpages_freed
    5 0 0 mem_err_slotpages_allocfailed
    7 0 0 aaa_otp_tot_verify_success
    9 0 0 aaa_otp_tot_verify_fail
    11 0 0 aaa_otp_tot_manage_success
    13 0 0 aaa_otp_tot_manage_fail
    15 0 10 dns_totpipelined_request

    The last Line: “10 dns_totpipelined_request” is the only Value thats change.
    Do you have any idea why this happens?

    1. The authentication in aaad.debug shows no error.
      Additional from /var/log/nslog:

      Sep 10 15:11:38 09/10/2019:13:11:38 GMT 0-PPE-0 : default SSLVPN Message 1249 0 : “vserver vs_citrixevalvpx. configured with Auth vserver auth_vs_otp_aaa, using auth for policies”
      Sep 10 15:11:38 09/10/2019:13:11:38 GMT 0-PPE-0 : default SSLVPN Message 1250 0 : “ns_aaa_advance_authn_policyeval: copying policylabel name auth_vs_otp_aaa to aaa info, type 33 for auth ”
      Sep 10 15:11:38 09/10/2019:13:11:38 GMT 0-PPE-0 : default SSLVPN Message 1251 0 : “aaad_advance_authnpolicy_handler: epa_action_head = 0x33870900 ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default SSLVPN Message 1252 0 : “core 0: ns_get_username_password: loginschema gleaned is Single_Manage_OTP-lschema ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default SSLVPN Message 1253 0 : “vserver vs_citrixevalvpx. configured with Auth vserver auth_vs_otp_aaa, using auth for policies”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default SSLVPN Message 1254 0 : “ns_aaa_advance_authn_policyeval: copying policylabel name auth_vs_otp_aaa to aaa info, type 33 for auth ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default SSLVPN Message 1255 0 : “aaad_advance_authnpolicy_handler: epa_action_head = 0x33870900 ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default AAATM Message 1256 0 : “core 0: sslvpn_aaad_login_handler: openid attributes len 42”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default AAATM Message 1257 0 : “(0-33) Authentication succeeded, current factor: auth_vs_otp_aaa, for user: %username” ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default AAATM Message 1258 0 : “(0-33) copying next factor otp_pol_label in aaa info for %username” ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default AAATM Message 1259 0 : “Nextfactor is either passthrough or client is 401 or legacy, user: %username” ”
      Sep 10 15:11:45 09/10/2019:13:11:45 GMT 0-PPE-0 : default AAA Message 1260 0 : “nFactor: Next factor otp_pol_label is configured as passthough/implicit, loginschema LSCHEMA_INT”

  16. Hi Carl, you mentioned that is necessary to use RfWebUI portal theme. Is there any specific reason to avoid using any other portal theme?

  17. Hello Carl,

    great article!

    Is it possible to pass through at the same publication / NetScaler Gateway vServer a gorup of users directly without OTP? (only with username and password)

    Regards,
    Gerard

  18. “HTTP.REQ.COOKIE.VALUE(\”NCS_TASS\”).EQ(\”manageotp\”)”
    Getting Expression Syntax error

    1. You’re entering that in the GUI? If so, then remove the extra \ in front of each double quotes. Also, make sure the quotes are straight up/down instead of curly.

      1. Tried but same expression syntax error… Could type gui expression.

        Does it support alternate OTP solution like ODA

        1. Hi,

          i’ve tested it a few moments ago and get the same expression error.
          In my case, i was able to fix it by retype the quotation marks in the expression.

    1. Does the Login Schema have the hidden field to enable manageotp? You can use your browser developer tools to see the form fields. If not, then you’ll need to review your configuration to determine why the wrong login schema is being displayed.

    2. Aunkub – This is because you’re trying to get to the /manageotp/ URL from ourside the internal network you have defined. The manageotp cannot be accessed external as per the configuration.

    3. Hi Aunkub – I saw this same issue; then I realized I was trying remotely from an external network and not the network internal to the netscaler. Make sure you connect inside your network as the configuration described in this article is designed to only register devices internally.

  19. Hi Carl, thanks for this write up. I have everything working currently in a test environment without ManageOTP being subnet restricted. Before rolling this out, we’re trying to figure out how we can get the device registration to work with users in a different country that don’t have physical access to our internal network. Is there a way to add multiple subnets into the http.req.cookie.value(“NSC_TASS”).eq(“manageotp”) && client.IP.SRC.IN_SUBNET(x.x.x.x/16) expression? Or do you have any suggestions on how they can register their devices remotely?

    1. Change it to:

      http.req.cookie.value(“NSC_TASS”).eq(“manageotp”) && (client.IP.SRC.IN_SUBNET(x.x.x.x/16) || client.IP.SRC.IN_SUBNET(x.x.x.x/16))

      You can certainly allow access to manageotp remotely, but it would only be protected by single factor authentication. Once the user has an enrolled device, you can use an existing enrolled device to protect manageotp.

      1. Thank you for the quick response. We figured out a workaround a little while ago. We’re going to have a week grace period to allow users to register then disable external manageotp access. Them for new users we’ll enroll their accounts internally and send them the QR manual code to register. Not the most secure but a workaround nonetheless.

  20. unfortunately the seed used for softtoken is still too short to meet the minimum requirements of the RFC, but now the 160Bit seed of the hardware tokens can be used, with version 13 this is also still a problem

  21. I’m trying to create the ‘Dual_OTP-lschema’ within my AAA Schema Profiles, but I keep getting an error ‘Content type doesn’t match the resource name’

    Any ideas?

    1. I saw that recently. I think I had to cancel adding the Login Schema and then try again. It eventually worked for me.

      1. I was missing the ‘AAA.USER.ATTRIBUTE(1)’ for the when creating the login schema. There was a section to place a 1 in the Credential index which caused the issue if the AAA attribute is not there. (I don;t think this was referenced in the instructions)

        1. Hi SImon,

          Where did you set this value as i am getting the same error. Any guidance you can give would be really good.

  22. Hi Carl,

    Good Day!!

    I am able to register the device on ManageOTP page but I want to achieve below things:

    1) Can we restrict users to register only 1 device per user whether on internal network or on external network. The reason why I am saying as there are some users who are on external network.

    2) Can I remove the Delete device button from Device registration as I do not want that user should be able to delete the device, they should rather call us to do the same.

    Kindly suggest.

    Thanks.

      1. Hi Carl,

        Thanks for your reply!!

        In order to prevent enrollment of additional devices, I have followed the below article shared by Stan Demburg:

        https://www.irangers.com/netscaler-native-otp-limit-enrollment-one-device/#comment-364

        While configuring the same, I have made a mistake while creating Authentication PolicyLabel. So when I trying to delete the PolicyLabel, it says “Resource in Use” & there are no policy binds with that Policy Label.

        Can you please help me in How can I delete the Policy Label or How can I check where it is being used?

        Thanks.

        1. I usually go to System > Diagnostics > Running Configuration, and then search the config for the Policy Label name.

          1. Hi Carl,

            Thanks for the prompt reply!!

            I checked the running configuration & found below for PolicyLabel:

            “add authentication policylabel OTP-2FA-Verify_pollabel -loginSchema LSCHEMA_INT”

            Now when I try to change the login schema from LSCHEMA_INT to other one using command & getting error:

            > add authentication policylabel OTP-2FA-Verify_pollabel -loginSchema OTP-Passcode-Only_lschema
            ERROR: Invalid Advanced Expression annotation value

            Also, it does not allow me to delete the PolicyLabel. When I am creating a new policylabel with the correct settings, that does not take affect.

            Please suggest.

            Thanks.

          2. Can you do the following?

            rm authentication policylabel OTP-2FA-Verify_pollabel

          3. Hi Carl,

            I tried to perform the following command:

            rm authentication policylabel OTP-2FA-Verify_pollabel

            But getting error : Resource in Use

            Thanks.

  23. Dear Carl,

    Thanks for your help.
    My NS to 12.1 build 51.19. I have configured the OTP Secret exact same way as mentioned in the article.

    I would like to restrict the /manageotp to my internal network with this rule in my login shema : http.req.cookie.value(“NSC_TASS”).eq(“manageotp”) && client.IP.SRC.IN_SUBNET(X.X.X.X/16)

    I can enroll my device from my internal network but also from the external network.

    Do you have an idea?

    Thanks for your reply

    Best regards
    Quentin

    1. Is your firewall doing any Source NAT for users connecting from the Internet? Maybe NetScaler is seeing a client IP that is the in the subnet in your expression instead of the true public IP.

      1. the problem is that if I put a network that is totally different from my infrastructure the rule doesn’t even seem to apply. I can continue to enroll from both the internal and external network.
        Should the rule of subnet restriction must be placed elsewhere than in the login schema?

        Thanks for your reply

        1. You should have two Login Schema policies. Only one of them should be for manageotp. The other one should be a normal two-factor schema.

          Did you bind the Login Schema Policies with the correct priority? The manageotp Login Schema policy should be evaluated first. If fails, then it should flow to the next Login Schema, which is two-factor with the manageotp code.

          1. Yes exactly.

            I have the First login schema with profile that have SingleAuthManageOTP.xml and on the policie expression : HTTP.REQ.COOKIE.VALUE(“NSC_TASS”).EQ(“manageotp”) &&client.IP.SRC.IN_SUBNET(192.168.1.0/24).

            On my second Login Schema is for Dual Auth and ont he poilice expression True

            Just to access at my gatway i have a Search Filter to allow only user member of a security group

    2. Was there ever a fix for this issue? I am having the same issue as well. While it does not show the schema for single auth, it shows the schema for dual auth but if you just type in your username and password and ignore the passcode and hit enter it will allow you to go to register devices.

  24. Is there a way to remove the AD attribute, unenroll, or lock out the OTP portion if the user name and passwords are correct but the OTP is wrong?

  25. Hi Carl,

    Thanks for the article.

    I have recently upgraded my NS to 12.1 build 51.19. I have configured the OTP Secret exact same way as mentioned in the article. However, for few users I am able to register the device & for some I am unable to register the device & getting error “Failed to add device”.

    I have created a test user & assign the exact same AD groups as failed one & that test one is able to register the device with no erorrs.

    Can you please help me regarding the same?

    Thanks.

    1. For the non-working users, is the userParameters attribute already populated? Active Directory Users & Computers has some tabs that might put info in the userParameters attribute.

      1. Hi Carl,

        Thanks for the prompt reply.

        You were bang on with the resolution. I changed the OTP secret to extensionattribute & able to enroll the devices successfully. I found that UserParameters are being used for those users for some applications.

        Thankyou very much once again for the resolution.

        Cheers.

    1. Do you mean you see the enrollment page but it fails when adding a device? That usually means the LDAP Bind account does not have permissions to update the Active Directory attribute.

  26. Hi Carl,

    Thanks for this article. Unfortunately the /manageotp does not work for me. I go directly to the login page with passcode field. I don’t understand where I set something wrong. Do you have an idea ?

    1. Make sure you access it with https:// at the front of the URL string. Otherwise, it will likely be doing a general redirect to the UG URL and asking for logon.

      1. Hi Carl,

        You can find my configuration below. I hope you will find the issue…

        # Extracted Config for: OTP_Vserver

        # DNS Name Servers
        # —————-
        add dns nameServer 172.22.2.20

        add dns nameServer 172.22.2.21

        # Cache Global Parameters
        # ———————–
        # *** Integrated Caching feature is not enabled. Cache Global bindings skipped.

        # SSL Global Parameters
        # ———————
        enable ns feature ssl
        set ssl parameter -denySSLReneg FRONTEND_CLIENT

        # Certs
        # —–
        add ssl certKey wildcard.cer -cert wd.cer -key wc.key
        add ssl certKey “GlobalSign Intermediate” -cert gsorganizationvalsha2g2r1.crt -inform DER

        # *** Get certificate files from /nsconfig/ssl

        # Cert Links
        # ———-
        link ssl certKey wildcard.cer “GlobalSign Intermediate”

        # AAA Global Settings
        # ——————-
        enable ns feature AAA

        # LDAP Actions
        # ————
        add authentication ldapAction 172.22.2.20 -serverIP 172.22.2.20 -ldapBase “DC=domain,DC=lan” -ldapBindDn ldap@domain.lan -ldapBindDnPassword ****** -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName samAccountName -groupAttrName memberOf -subAttributeName CN

        add authentication ldapAction 172.22.2.20_OTP_SET_NO_AUTH -serverIP 172.22.2.20 -serverPort 636 -ldapBase “DC=domain,DC=lan” -ldapBindDn ldap@domain.lan -ldapBindDnPassword ****** -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName sAMAccountName -groupAttrName memberOf -subAttributeName cn -secType SSL -authentication DISABLED -OTPSecret extensionAttribute2

        add authentication ldapAction 172.22.2.20_OTP_VERIFY_NO_AUTH -serverIP 172.22.2.20 -serverPort 636 -ldapBase “DC=domain,DC=lan” -ldapBindDn ldap@domain.lan -ldapBindDnPassword ****** -encrypted -encryptmethod ENCMTHD_3 -ldapLoginName sAMAccountName -searchFilter “extensionAttribute2>=#@” -groupAttrName memberOf -subAttributeName cn -secType SSL -authentication DISABLED -OTPSecret extensionAttribute2

        # LDAP Policies
        # ————-
        add authentication ldapPolicy 172.22.2.20 ns_true 172.22.2.20

        # Advanced Authentication Policies
        # ——————————–
        add authentication Policy KARP-Adv -rule true -action 172.22.2.20

        add authentication Policy LDAP_MANAGE_OTP-Pol -rule “HTTP.REQ.COOKIE.VALUE(\”NCS_TASS\”).EQ(\”manageotp\”)” -action 172.22.2.20_OTP_SET_NO_AUTH

        add authentication Policy LDAP_VERIFY_OTP-Pol -rule true -action 172.22.2.20_OTP_VERIFY_NO_AUTH

        # Login Schema Policies
        # ———————
        add authentication loginSchemaPolicy Single_Manage_OTP-lschemapol -rule “HTTP.REQ.COOKIE.VALUE(\”NCS_TASS\”).EQ(\”manageotp\”)” -action Single_Manage_OTP-lschema

        add authentication loginSchemaPolicy DUAL_OTP-lschemapol -rule true -action Dual_OTP-lschema

        # Authentication Policy Labels
        # —————————-
        add authentication policylabel OTP_pollabel -loginSchema LSCHEMA_INT
        bind authentication policylabel OTP_pollabel -policyName LDAP_MANAGE_OTP-Pol -priority 100 -gotoPriorityExpression NEXT
        bind authentication policylabel OTP_pollabel -policyName LDAP_VERIFY_OTP-Pol -priority 120 -gotoPriorityExpression NEXT

        # Authentication Virtual Servers
        # ——————————
        add authentication vserver OTP-AAA SSL 0.0.0.0
        bind authentication vserver OTP-AAA -portaltheme RfWebUI
        bind authentication vserver OTP-AAA -policy Single_Manage_OTP-lschemapol -priority 100 -gotoPriorityExpression END
        bind authentication vserver OTP-AAA -policy DUAL_OTP-lschemapol -priority 110 -gotoPriorityExpression END
        bind authentication vserver OTP-AAA -policy KARP-Adv -priority 100 -nextFactor OTP_pollabel -gotoPriorityExpression NEXT

        # ** nFactor Visualizer
        # ** ——————
        # ** AAA vserver: OTP-AAA
        # ** Login Schema Policy = Single_Manage_OTP-lschemapol
        # ** Priority = 100
        # ** Login Policy Rule = “HTTP.REQ.COOKIE.VALUE(\”NCS_TASS\”).EQ(\”manageotp\”)”
        # ** Login Schema XML = “/nsconfig/loginschema/LoginSchema/SingleAuthManageOTP.xml”
        # ** Login Schema Policy = DUAL_OTP-lschemapol
        # ** Priority = 110
        # ** Login Policy Rule = true
        # ** Login Schema XML = “/nsconfig/loginschema/LoginSchema/DualAuth.xml”
        # ** Adv Authn Policy = KARP-Adv
        # ** Priority = 100
        # ** Authn Policy Rule = true
        # ** Authn Action = ldapAction named 172.22.2.20
        # ** Goto if failed = NEXT
        # ** Next Factor if Success = OTP_pollabel
        # ** Login Schema Profile = LSCHEMA_INT
        # ** Adv Authn Policy = LDAP_MANAGE_OTP-Pol
        # ** Priority = 100
        # ** Authn Policy Rule = “HTTP.REQ.COOKIE.VALUE(\”NCS_TASS\”).EQ(\”manageotp\”)”
        # ** Authn Action = ldapAction named 172.22.2.20_OTP_SET_NO_AUTH
        # ** Goto if failed = NEXT
        # ** Adv Authn Policy = LDAP_VERIFY_OTP-Pol
        # ** Priority = 120
        # ** Authn Policy Rule = true
        # ** Authn Action = ldapAction named 172.22.2.20_OTP_VERIFY_NO_AUTH
        # ** Goto if failed = NEXT

        # Authentication Profiles
        # ———————–
        add authentication authnProfile OTP-authnprofile -authnVsName OTP-AAA -AuthenticationHost OTP_Vserver

        # NetScaler Gateway Traffic Profiles
        # ———————————-
        add vpn trafficAction OTP-Trafficprofile http -passwdExpression “http.REQ.USER.ATTRIBUTE(1)”

        # NetScaler Gateway Traffic Policies
        # ———————————-
        add vpn trafficPolicy OTP-Trafficpol true OTP-Trafficprofile

        # NetScaler Gateway Session Profiles
        # ———————————-
        add vpn sessionAction AC_WB_192.168.2.5_S_ -transparentInterception OFF -defaultAuthorizationAction ALLOW -SSO ON -icaProxy ON -wihome “https://xendesktop.domain.lan/Citrix/DomainWeb” -ClientChoices OFF -ntDomain DOMAIN -clientlessVpnMode OFF

        # NetScaler Gateway Session Policies
        # ———————————-
        add vpn sessionPolicy PL_WB_192.168.2.5 ns_true AC_WB_192.168.2.5_S_

        # NetScaler Gateway Global Settings
        # ———————————
        enable ns feature SSLVPN
        set vpn parameter -clientSecurityLog ON -transparentInterception ON -proxy BROWSER -forceCleanup none -clientConfiguration all -wiPortalMode NORMAL -UITHEME GREENBUBBLE
        set aaa parameter -maxAAAUsers 4294967295
        add dns suffix domain.lan

        # NetScaler Gateway Virtual Servers
        # ———————————
        add vpn vserver OTP_Vserver SSL 192.168.2.6 443 -Listenpolicy NONE -authnProfile OTP-authnprofile
        bind vpn vserver OTP_Vserver -staServer “https://xendesktop.karpkneip.lu/scripts/ctxsta.dll”
        bind vpn vserver OTP_Vserver -portaltheme RfWebUI
        bind vpn vserver OTP_Vserver -policy 172.22.2.20 -priority 100
        bind vpn vserver OTP_Vserver -policy PL_WB_192.168.2.5 -priority 100
        bind vpn vserver OTP_Vserver -policy _cacheTCVPNStaticObjects -priority 10 -gotoPriorityExpression END -type REQUEST
        bind vpn vserver OTP_Vserver -policy _cacheOCVPNStaticObjects -priority 20 -gotoPriorityExpression END -type REQUEST
        bind vpn vserver OTP_Vserver -policy _cacheVPNStaticObjects -priority 30 -gotoPriorityExpression END -type REQUEST
        bind vpn vserver OTP_Vserver -policy _mayNoCacheReq -priority 40 -gotoPriorityExpression END -type REQUEST
        bind vpn vserver OTP_Vserver -policy _cacheWFStaticObjects -priority 10 -gotoPriorityExpression END -type RESPONSE
        bind vpn vserver OTP_Vserver -policy _noCacheRest -priority 20 -gotoPriorityExpression END -type RESPONSE
        bind vpn vserver OTP_Vserver -policy OTP-Trafficpol -priority 100 -gotoPriorityExpression END -type REQUEST

        # SSL Virtual Servers
        # ——————-
        bind ssl vserver OTP_Vserver -certkeyName wildcard.karpkneip.lu.cer
        bind ssl vserver OTP_Vserver -eccCurveName P_256
        bind ssl vserver OTP_Vserver -eccCurveName P_384
        bind ssl vserver OTP_Vserver -eccCurveName P_224
        bind ssl vserver OTP_Vserver -eccCurveName P_521

        bind ssl vserver OTP-AAA -certkeyName wildcard.cer
        bind ssl vserver OTP-AAA -eccCurveName P_256
        bind ssl vserver OTP-AAA -eccCurveName P_384
        bind ssl vserver OTP-AAA -eccCurveName P_224
        bind ssl vserver OTP-AAA -eccCurveName P_521

  27. Hi Carl,

    I can’t thank you enough for all the great articles you have put together. Saved my butt many times.

    I am currently replacing our On Prem MFA (previously known as phone factor) with OTP from a new SDX. Is there a way to have a sec group to point users to NS OTP?

    We want to slowly migrate to OTP from phone factor. The defualt login would be how it is now, User name + password and on prem MFA.

    I’d like to be able to have a security group that forces users to OTP login..

  28. Hi,

    Is there any way to hide the “userParameters” hash value in the AD User Attribute? Because, the administrator can see the user’s OTP secret value and add this into his mobile to get the OTP for that user.

    1. The device registration process has too many security concerns for me to ever recommend the native OTP feature. Hopefully Citrix can figure out a way to tighten the configuration.

      1. Hi,

        I have done some testing and If deployed on a “Unified Gateway” and we don’t enter || HTTP.REQ.URL.CONTAINS(“/manageotp”) on the content switching policy for the Gateway. This then would block device enrollment externally from the gateway portal. To enable device enrollment I pointed a new content switching VIP to the AAA server this allowed me to enroll devices but also apply additional ACL’S to restrict access to the page.

        Does this remove some of the security concerns around the device enrollment process?

        In current testing the following expression below that was mentioned in this article does not seam to function, this is why I was looking into this further

        http.req.cookie.value(“NSC_TASS”).eq(“manageotp”) && client.IP.SRC.IN_SUBNET(X.X.X.X/16)

  29. Hi Carl, When you wrote “NetScaler Native OTP is part of nFactor, and thus requires NetScaler Enterprise Edition or NetScaler Platinum Edition licensing. NetScaler Standard Edition licensing is not sufficient.”. This applies only on Citrix ADC licence ? Because it’s include when you have Citrix Gateway Licence. Can you confirm that ? Br, Julien

    1. Needs to be ADC Advanced or ADC Premium.

      The Gateway only license is a subset of ADC, so anything that requires a higher ADC edition will not be in the lower Gateway edition.

  30. Hi Carl,

    Have gone through all config steps, everything should be ok, but
    after the standard domain logon on the /manageotp site, whan I try to register a device name, I always get the error “Failed to add ”
    And I can not find anything regarding this error anywhere.

    – Is this an AD write problem?

    – Or does the Citrix GW or the client browser (which is requesting the GoogleAuthenticator-based device adding) need access to some other servers outside?

    – Generally, for Google Authenticator to work with the Citrix Native OTP, which component needs internet access to which server(s)? Or is no internet access (namedly to any Google Auth servers) needed, because the CTX GW is managing the whole GoogleAuthenticator implementation internally?

    Thank you
    Udo

    1. Meanwhile tested with some other users and found that everything does work as expected when I try the OTP device setup with the user I configured as “LDAP Administrator Bind DN”.

      I know that this Administrator Bind DN user needs to have read access to the AD OTP Secret of cause, but in this case the Administrator Bind DN test user is domain admin who has got all necessary rights.

      But even when I try the OTP device setup with another domain admin with the same rights, it does not work.
      OTP login setup is only working with exactly this one user that I configured in the CTX GW LDAP Administrator Bind DN.

      Any ideas?

      1. Again digged a little deeper and found that the connection between the Admin Bind DN and the “good” user was pure coincidence:
        This Admin user simply had no data in the “userParameters” AD attribute and the other domain users already had some data in there coming from other Citrix parts.
        As I suspected that this might be a problem before I set up this OTP part, also because you stated in your docs that the userParameters attribute could be used if not used otherwise and because the “other” parts also came from Citrix, I confirmed with Citrix Support that the string will only be appended and will not interfere with the parts already present and they confirmed that this is ok, as all Citrix parts should be aware of this.

        But as I found out now, in reality, as soon as *anything* is already present in that attribute, we will always get the error I had written above and as soon as we clear the contents, everything is ok and the device registration QR code is successfully generated and the AD attribute correctly written.

        As most of the admins here will also run Citrix VDAs and other stuff and will have the same situation that the userParamaters attribute is already polulated, but still it is suggested to be used: What is the solution here? And which other attribute is save to be used as a workaround?

    2. Just a side comment. Google Authenticator has nothing to do with Google servers or internet at all. The correct name to use here is TOTP, and Google Auth. is just one of many TOTP apps

      1. Hi Emin,

        Thank you, yes, meanwhile I’ve seen that the whole implementation is done offline by the Citrix NSGW and only uses the open source TOTP implementation, which is good to know and answering the second part of the question.

        Still the main issue here is the non-usability of the suggested AD attribute in case there is any other Citrix SW installed which is also using it.
        Maybe someone can confirm this and suggest any other AD attribute which can be used without having to fear side effects?

  31. Hi Carl. Wanted to point out something regarding the /manageotp Single Factor Auth Page.

    I have restricted my OTP Management page to Private IPs only, but found another way to access from the Internet (which is very bad!).

    VPN url: https://vpn.example.com
    ManageOTP url: https://vpn.example.com/manageotp

    Browsing to the /manageotp will redirect to the 2fa login of VPN url (since it is restricted by a policy). But if from the 3 fields, you populate just the Username and Password of the 2fa login, you can still access the manageotp page.

    Maybe i have something wrong in my config?

    Manuel

      1. Already doing this on both the Login Schema and Advanced Authentication Policy (OTP Management) with:

        http.REQ.HOSTNAME.EQ(“otp.domain.com”) && client.IP.SRC.IN_SUBNET(192.168.0.0/16)

        I have to bind the Responder Policy to the AAA vServer?

          1. or maybe even better binding it to the CS or NG vServer?

            accessing https://vpn.domain.com/manageotp is redirecting me to the 2fa login page, but still populating the Username and Password field is redirecting me to the OTP Management page.

  32. Hi Carl, I’ve tried twice now going through these steps, but whenever it try to go to the /manageotp site I get stuck in the the age old “Cannot complete request” loop. Where do I start looking?

  33. HI Carl i have an issue when trying to export the configuration of the netscaler gateway i have the latest version available 50.28 and using a a trial key and after configuring the netscaler gateway with storefront authentication the zip file i dont think it is created when trying to export it becuase i get a messgae from the browser file not found

      1. i missed out this piece of information it is running on hyper v 2012r2 and indeed it is a bug since i downgraded the vpx 12.1 version to 49.37 release from 50.28 and the bug is gone and i could successfully export and import the gateway configuration to the storefront

    1. Hardware Tokens are now supported and are working. (we had a long open case about this with Citrix)

      You will need a TOTP token that support 30s SHA-1 or SHA-2 Algorithm and then modify the AD Attribute and add you Token with the Base32 Seed and algorithm that is used.

      I can share more infos if this is wished.

      BR,
      Kim

  34. Hi Carl Stalhood,
    This feature this support 1factor and 2factor simultaneous? If user not create register OTP, It’s can connect with 1factor.

  35. Hi, I have a customer that’s requesting to translate the OTP page to Dutch. (“Enter the verication code you receive via a text message”). I have no clue where to look for. Can you please help me ? Thx

    1. Hey Kisiel,
      Not sure why the “text message”. Are you using NetScaler’s native OTP or third-party? The native OTP does not support text messages.

      In case of third-party MFA, this is likely managed by your third-party MFA solution and consumed by NetScaler via RADIUS.

      In case you do use the native OTP, you can modify the nFactor LoginSchema XML file:
      – Create a new login schema
      – Use WinSCP (for example), connect to your NetScaler
      – Navigate to /flash/nsconfig/loginschema
      – Edit your login schema .XML file

      You can add something like this:

      none
      Please enter the six-digit authenticator code (from your smart device)heading

    2. Hey Kisiel,
      Looks like you are using a third-party MFA and not NetScaler’s native OTP as native OTP does not support text messaging. With third-party MFA this is probably managed by the MFA solution and pushed to NetScaler over RADIUS.

      In case you use NetScaler’s native OTP, this can be modified in the Login Schema. Use WinSCP or similar to navigate to /flash/nsconfig/loginschema and modify your Login Schema .XML file.

  36. Hi Carl
    One question about OTP Traffic policy section here,

    “If your NetScaler Gateway Virtual Server allows full VPN, change the expression to the following. Source = Julien Mooren at NetScaler – Native OTP is breaking SSL VPN.
    http.req.method.eq(post)||http.req.method.eq(get) && false”

    The expression’s result here seems always being false.
    http.req.method.eq(post)||http.req.method.eq(get) && false
    May I know what’s that use for?

  37. Hi Carl, do you know if the length of the secret key (OTP secret) can be modified? By default it generates only 16 chars long base32 string (20 hex)- but this is not really long enough. I would like at least 40 hex

  38. Is it possible to create a PowerShell script to query Users who have content in the userParameters attribute field? I would like to be able to create a report based off this data and this subset of Users. Can someone provide such a script? I have limited knowledge dealing with PowerShell.

  39. I receive the following error when entering the username/password/passcode.

    Please log on
    The server met an error. Please try again or contact your administrator.

    It never gets to the storefront apps

  40. Looks like you have a typo in your CLI config:
    bind authentication policylabel OTP_pollabel -policyName LDAP_verify_OTP-pol -priority 110 -gotoPriorityExpression NEXT

    should be?

    bind authentication policylabel OTP_pollabel -policyName LDAP_confrim_OTP-pol -priority 110 -gotoPriorityExpression NEXT

  41. depending on your active directory settings, it may happen that your AD-User Accounts may be locked after a certain amount of failed logins.
    To prevent some kind of DOS attack against your AD accounts having an totp setup like this in public i suggest the following modification of the above setup:
    1. when creating the ldap authentication server “LDAP-Corp” uncheck the box “Authentication”
    2. create a copy of “LDAP-Corp”, e.g. “LDAP-Corp-userauth” and use this in an additional “Authentication Policy” in your AAA vserver after “Corp-adv” (e.g. priority 120) by using an additional policy like “Corp-adv-userauth”

    Btw. you may use this totp setup with an loadbalancing vserver and single-sign-on with a backend webserver by creating a session policy in your aaa vserver with settings “Single-Sign-on to Web-Applications: On” and “Credential Index: Primary”. Beware of setting “Single Sign-on Domain” – it worked for me only when leaving it empty

      1. Hi CLU,

        in the Company Network your users should go directly through StoreFront, not Citrix Gateway – so there is no OTP auth.

        1. That isn’t necessarily true.

          HDX Insight data is not available for the entire path unless the traffic goes through a Citrix ADC. Additionally, the use of step-up authentication to require a token / OTP, even from an internal network, for certain applications is often desirable.

          The Authentication Policy can be augmented so that it ‘skips’ the OTP piece when connections are seen from certain IP Addresses (internal).

Leave a Reply

Your email address will not be published. Required fields are marked *