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

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


Change Log


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(
    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.
  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")


  1. Point your browser to 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 -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 -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 -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(" -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
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 SSL 443 -downStateFlush DISABLED -Listenpolicy NONE -authnProfile OTP-authnprofile
set ssl vserver -sslProfile ns_default_ssl_profile_frontend
add vpn sessionAction "Receiver For Web" -transparentInterception OFF -defaultAuthorizationAction ALLOW -SSO ON -icaProxy ON -wihome "" -ntDomain corp.local -clientlessVpnMode OFF -storefronturl ""
add vpn sessionPolicy "Receiver For Web" "HTTP.REQ.HEADER(\"User-Agent\").CONTAINS(\"CitrixReceiver\").NOT" "Receiver For Web"
bind vpn vserver -portaltheme RfWebUI
bind vpn vserver -policy "Receiver For Web" -priority 100 -gotoPriorityExpression NEXT -type REQUEST
bind vpn vserver -policy OTP-trafficpol -priority 100 -gotoPriorityExpression END -type REQUEST
bind ssl vserver -certkeyName WildcardCorpCom

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

  1. Hi Carl,

    Your tutorial works like a charm, but I have a problem with certain users. When I erase the userParameters field in the AD the user is no longer able to connect a new OTP device. Also there is not any device listed in the manageotp site after a new device registration. Althought the new device is published to the AD. Is there some caching functionality on the netscaler that also stores a copy of the OTP key per user?


  2. Just found another dilemna. since enabling this 2 factor authentication, users can’t authenticate successfully when the “user must change password at next logon” flag is checked. This is both for the main page and /manageotp…

  3. I wish it could pull the “mail” attribute from AD for the user, and email them a code to enroll. Having access to the email account would be the 2nd factor just for enrollment purposes, then they’d setup their authenticator from there…

    I really want to use native OTP, but i’m struggling to figure out a reasonable process for self-enrollment from anywhere.

  4. Thank you for your great step by step instructions. So far everything is working, was able to register my phone and using the OTP to login into the system. I just noticed if a user enters a wrong password (username and otp is valid) netscaler is showing the error “Request can not be completed” (translated from german).
    Is this the typical behaviour? Any thoughts how to fix that are welcome.

    1. I missed to check the “Authentication” box for the LDAP-Corp server.
      Now everything is working great!

  5. Hi All,
    Is it possible to have only one device enrolled and not multiple? Can this be limited somehow? Eg check if the AD user property is already populated and if so, new device enrollment is routed to the support desk to have the attributes reset (in case of a new device, lost or stolen or whatever).

    1. In a Synergy session, Citrix said there’s way to limit. I asked for more info, and haven’t seen it yet.

      1. Hi Carl, In the end it’s a Java page I guess, so the code should be changeable. If attribute.contains(something) = true, do not allow changes, do not show the delete/add buttons. If attribute.contains(something) = false, do roll out and show recovery code. Any idea which page it is in NetScaler? Maybe I can have a look myself. …

        1. I was thinking of a policy expression that checks the attribute to see if it’s already populated or not.

          I suspect manageotp is generated by the appliance.

          1. OK, so the appliance generates the page based on the login schema provided and the RfWebUI template? I think if we can check the attribute with an expression, we can redirect to a ‘sorry’ page. This policy expression should be binded just before the enroll policy. Any ideas howto? I think this setup is not production worthy or GPDR compliant …

          2. Hi Carl,
            Any ideas how to create such a policy that checks for the user attribute being set or not?

          3. Hi Stan, ltx for sharing, ooks promising. Tldr, can a 2nd factor user remove and reenroll a new device? This would create the same pitfall again.

          4. This config won’t let users enroll any additional devices internally and cut the access to /manageotp. If the user is trying to access the /manageotp, he will be prompted for OTP and then end up on the NetScaler Gateway portal.

          5. Hi Stan, also left a note on your blog, I could’t get the config to work, tried both GUI and CLI. The CLI doens’t allow me to bind a classic polcy, because there is an advanced VPN policy bound. No clue on this one. This are the commands that fail:

            bind aaa group NS-Internal-OTP-Verified -policy RDP-and-Web-CTX-Apps_spol -priority 100
            bind vpn vserver -policy ICA-Proxy-Only_spol -priority 100

            The error I get is:
            ERROR: Classic VPN Session Policy cannot be bound if Advanced VPN Session Policy is already bound to any entity (i.e. aaa user, aaa group, vpn vserver, vpn global)

            Any ideas?


          6. Hi Ronald,

            Please run the following CLI commands (they will create and bind Advanced session policies). Change the “” to your NetScaler Gateway vServer name:

            add vpn sessionPolicy ICA-Proxy-only_advspol “HTTP.REQ.HEADER(\”User-Agent\”).CONTAINS(\”CitrixReceiver\”)” ICA-Proxy-only_prof
            add vpn sessionPolicy RDP-and-Web-CTX-Apps_advspol true RDP-and-Web-CTX-Apps_sprof
            bind aaa group NS-Internal-OTP-Verified -policy RDP-and-Web-CTX-Apps_advspol -priority 100
            bind vpn vserver -policy ICA-Proxy-Only_advspol -priority 100

          7. Hi Stan,
            I was able to do add the advanced polices. When I try to login, I receive the error (circled red cross):
            “Session absent to manage otp for user; probably misconfiguration.”
            I am positive I made no typos. Any ideas on this one? I can post my CLI commands here or PM them is you prefer (and if you are willing to have a look of course). I am using latest v12.0 build (57.24).

            I also made a clean up CLI book which I can share, so you easily reprovision.

            Hope you can help me out.

            Best regards,

          8. Hi Stan,

            Thanks for helping me out! Stupid, the AD group did the trick of course. Sorry for that one. I was able to enroll a device with Google Authenticator. But when I normally enter storefront, I receive this error:

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

            In the ns.log/nsvpn.log/aaad.debug etc I do not see any errors.

            The StoreFront server is also servicing other NetScaler vServers to this same user (only UPN based) without any problem. The windows eventlog upon Citrix Delivery Services is also clean.

            Any ideas on this one?


          9. Hi Stan,

            changed the LDAP actions to use UPN, but that didn help either. The user AD property is populated with the deviceID and stuff, and the enrollment and test works fine. I am using extentionAttribute15 instead of userParameters, because I have a mixed RDP and Citrix environment. I edited of course the LDAP actions accordingly. Still got the error:

            The server met an error. Retry or contact administrator.

            If you have any further ideas?

            Or drop me a line at ronald at, so I can send you the complete config (and reverse order to clean things up).


      2. Hi Carl,

        How can we configure expiration of Generated TOKEN (passcode), We are using Citrix SSO as our Authenticator but after one day we can still used the generated passode from the other day.

  6. Is it possible to incorporate the OTP with a pre-authentication EPA scan? I can’t get my policy right so that the EPA does not kick in for the manageotp internal only authentication page.


  7. Hi All,
    The validatoion works, but now I receive a Could not complete your request, when I normally get my apps. I had this one before back then it was the STA settings, but now it’s not. Got a public certificate and all..
    Any ideas?

    1. What do you see in StoreFront Server > Event Viewer > Applications and Services > Citrix Delivery Services?

      1. Had the default domain property populated in the session profile. Cleared that one and now all works!

  8. Hi Carl,
    Something more to add, the userParameters is not filled after I enrolled my device. Is this also why the test will fail? I assume that if a device gets enrolled, this is immedeatly written in the userParameters property of the user. Or do I get this wrong?

    1. Yea, account operators was not sufficient here. Scaled permissions up and that worked! BTW, I have a combo of RDS and XenApp deployments and the userParameters is used by RDS as well. Switched my deployment to use an extensionAttribute user property instead. Maybe that is of help for more out here.

  9. Hi Carl,

    Excellent write up and thans for all the effort you put in it.

    I do not get past the point where I can Test the OTP enabled account. I log in with /manageotp, I can add my device (iphone with GA), I get the barcode, GA adds my account to my iphone, then if I do Test it says ‘Failed to Verify OTP from iPhone’.

    I checked the time on the NS, but that is syncing fine with NTP. On the console it shows the correct time. From the NS I can also do a telnet to 443 to, so guess that’s all fine.

    Any idea what goes wrong here?



  10. Did you see the presentation at Synergy around OTP, there is a CitrixSSO app for the OTP now and it supports using Push notifications along with your device pin/biometrics to be the second factor, have been trying it today, but doesn’t seem that the Login Schema settings are available to get the logon with Push notifications checkbox on the logon screen yet.

      1. The Login Schemas are present on the new NetScaler 12.1 release called DualAuthOrPush.xml and SingleAuthDoPush.xml but you need to configure a Push Service and not too sure what to enter in there yet.
        They did mention during the OTP session at Synergy they were going to let all NetScaler users use their hosted push notification servers but they haven’t shared how we use it yet.

  11. Hi Carl,

    I complete the guide and I can login with OTP. After I’m singned in (remote) I can see all my published destops. But when I start one of those desktops it keeps connecting. In the end I’m getting the following error: The published resource is not available currently.

    When I try to logon on the local LAN it works perfectly.

    Any ideas?


      1. No that doesn’t work. I can see my published applications but as soon as I click on them they keep connecting. (remote login from Internet).

        When I try this on my local LAN it’s working fine.

        The netscaler is in my DMZ and my Storefront and Desktop servers are on two seperate networks devided by a firewall.

  12. Hi,

    Don’t you know how to configure NetScaler (and StoreFront) with OTP for iOS Receiver?
    iOS Receiver has different behavior from other Receiver and browser, so special settings like CTX125364 is necessary.
    Then how can we configure NetScaler?

    1. nFactor support for Receiver is coming in Q3/Q4 2018 according to Citrix at Synergy this week, so not long to go!

  13. If you get the error “Failed to verify incoming OTP value” make sure you got the right time set. In doubt? check through the CLI the ‘date’. Check if it is the same as the GUI system time.

  14. Hi Karl, great article! looking implement OTP in production and was wondering what NC12 code level you feel is the most stable. Would there be any citrix recommended firmware release?

    Thanks you!

    1. Citrix is still adding features to NetScaler 12. If you go with 12, and if a security bulletin is released requiring you to upgrade, then you’ll be forced to add new features.

      11.1 should not be receiving any more new features, but it doesn’t have OTP.

  15. Hi Carl, I came across an issue while implementing your steps. OTP works no problem but when I establish a SSL full VPN tunnel I cannot access any protocols e.g. I cannot RDP to my servers etc. Only HTTP flowed through the tunnel. Identified this was caused by the traffic policy. Having it set “true” steps all traffic except HTTP. I changed it from true to “client.TCP.DSTPORT.EQ(80)” to enable other traffic to flow. Now I don’t know what it will break. Your thoughts?

  16. Hey Carl, Thank you so much for this information. I keep getting external access is denied for my user when using the netscaler VIP. I have configured the manageotp for my device but for external access, I get this error. The firewall is already configured properly. Is there a LoginSchema expression syntax I should use to allow external access?

  17. Since I have encountered problems with NetScaler OTP i want to mention this forum thread i created:

    meanwhile we have another client with the same problem, exact same group cap with the same configuration used (this article) but of course different environments. We will open a ticket with Citrix and i will try to keep the forum post updated, so you guys can check on it if you run into same issue(s).

  18. Am I the only one who is a bit concerned about the fact, that NetScaler basically writes the Seed used for OTP generation in cleartext into an AD-Field which people could just read and use it to re-assemble any OTP? Or am I seeing this the wrong way?
    Article is great, worked like a charm for me though!

    1. No, you are not the only one, I wrote a comment on the issue further down. But what you can do is to set the Confidential bit on the attribute you’re using and allow the NS service account to see it. When setting that bit the attribute will be hidden for users not granted specific access to it. And you should use another attribute than userParameters as it is used for RDS profile information. Setting the Confidential bit on that attribute probably will cause strange behavior for users.

  19. Hi Carl

    I just wonder if we can use this solution to send a text message to users who need dual authentication. This is the key point for us

    As from this article looks like we need to use google authenticator

  20. Hi Carl

    What to do, if we want a certain AD group/user to access without been promptet for OTP,
    but just username/password ?

    1. Hi Oleg, I think I might have the same ‘issue’. Could you please explain a bit more detailed what you did change?
      That would be great.


  21. Thanks for good article!
    Complete test deployment Netscaler 12 OTP at my production environment yestoday.
    While testing some accounts got error about “OTP verify”, some didn’t. All record and device registration were correct. Further investigation led to conclusion that netscaler badly search for the “userParameters” attribute if account is a memeber of many AD-groups. To check that i just remove all groups exept domain users and Remote_Citrix (AD group for remote connection) and Whoola! Verify OTP passed!
    To resolve that issue i had to reduce search filter for “OTP_verify_no_auth” to single remote AD-group at the Authentication LDAP Server Configuration.

  22. Hi Carl, I want to create the manage OTP policy (step 7d), but the Expression HTTP.REQ.COOKIE.VALUE(“NSC_TASS”).EQ(“manageotp”) is not accepted. I always get ‘Expression syntax error’. Did something maybe change? I’m on Netscaler
    Or what is wrong?

    Thx for your help.

  23. Hi Carl
    Thank you for this very useful documentation.

    I still have an issue. When trying to add an device I can type in the name but I when click on OK nothing happens.

    Do you have any idea why?

    Regards Tobias

  24. Hi Carl,

    I did a POC with NetScaler OTP, everything worked as expected. Now I need to do production deployment in a phased manner, so I have created 2 groups ExternalAccess-LDAP & ExternalAccess-OTP.

    1. NS GW access is not restricted to a group today
    2. I want to present just the username screen, get the user name and present with next factors based on membership – either password only or password and OTP. I need to change the default login schema to username field only.
    3. Once all the users are onboard with OTP, I will leave the LDAP group empty so that I can use it as back door entry if needed in future. User lost the mobile, etc.
    4. Native Receiver authentication policy should be user name and password, I will restrict it to a separate group as Native Receiver doesn’t support OTP.

    I followed this article to create diff authentication policies based on group membership, I am not able to present different login schemas based on the factor.

    Can you suggest how should i go about it?


  25. Hi Carl,
    I need your advice.
    Can you suggest me configuration for this use case:

    Currently I have a regular LDAP + Radius OTP login to my netscaler.
    I want to give the user the choice if to use the new Native OTP or the organization OTP using a drop-down menu.
    Is it possible?

  26. Hi Carl,
    I have the following problem:
    A user who is not on the subnet, which is allowed to access /manageotp, can simply type /manageotp in the URL and will be taken to the login pages with the three fields. If the user logs in with his AD login he will be taken to the manageotp page.
    Is that the same for you guys? Or do I have a configuration error?

    thank you

  27. Hi Carl, is there a way to redirect the traffic to external vendor site instead of landing in storefront for this OTP setup? thank you very much.

    1. I assume this is a normal AAA configuration and you can use any other AAA or Unified Gateway configurations.

  28. Just one thing when testing native otp feature…
    Do not enable “nested group extraction” on your otp management LDAP Auth Server…. this will break writing the OTP Secret to the AD Attribute (e.g. userparameters).

    1. This is a bug and Citrix gateway team is working on fix. If nested group extraction is configured in ldapaction, we are not registering device

  29. OK, so I believe I am 90-95% there. I believe NetScaler Gateway is “successfully” authenticating me against both sets of credentials (AD and Google Authenticator), but I get the “Cannot complete your request” error from StoreFront. What I see in the Event Logs on the StoreFront server is a “Citrix Authentication Service” event (ID 7) stating:

    CitrixAGBasic single sign-on failed because the credentials failed verification with reason: Failed.

    What follows shows is interesting. The “username” field is populated with the password, which appears to suggest the NetScaler has passed through the wrong value. What have I done wrong for this to be the case? I’ve been through this article twice, and there appears to be nothing that I have missed. Is there any other configurations I should know about (i.e. in StoreFront)? If I remove the OTP configuration from the NetScaler Gateway, I authenticate successful to NetScaler Gateway and StoreFront.



    1. In the Login Schema Profile, there’s a Password Credential Index. That should be a unique number that you later use in the Traffic Policy. You can also configure a different attribute number for the User Credential Index.

      1. Ah, I found my issue. I put the “http.REQ.USER.ATTRIBUTE(1)” expression in the Traffic Profile into the SSO User Expression, not the SSO Password Expression. Great little “hack” though if you want to find out someone’s password via the Event Logs (only have LDAP available here, not LDAPS).

        Thanks Carl.

  30. Hi Carl,

    Just wondering if you know how to deal with multiple internal subnets for the Single Authentication Login Schema policy?



    1. Are you able to specify a summary route?

      Or, you can add multiple subnets inside a parentheses clause with || (OR) between them. This is standard Boolean expression.

  31. Suggestion for make it easier to the users to enroll their token. I would create a responder policy for the redirect to the substring “/manageotp”.

    1.) Create a new dns record which is pointing to the NetScaler Gateway VIP –>
    2.) Create a responder action and policy
    add responder action resp_act_manageotp redirect “\”\”” -responseStatusCode 302
    add responder policy resp_pol_manageotp “HTTP.REQ.HOSTNAME.CONTAINS(\”\”)” resp_act_manageotp
    3.) Bind the responder policy to your Gateway.
    bind vpn vserver -policy resp_pol_manageotp -priority 100 -gotoPriorityExpression END -type REQUEST


    1. How are you locking it down so that the manageotp registration is not available externally? Whats the point of two factor auth if a hacker just needs a password and can then register his own token externally.

      I have read some stuff on locking it down by subnet but we want our users to be able to self service and have over 100 subnets. This would be a significant rule to setup. Any other options?

  32. Ignore my previous post – one typo derailed the entire thing.

    Another question though – Is there any way to scope this so that only the users that want to use nFactor are presented the additional dialog? Enabling this on a global scale would create a huge headache when my user base would attempt a login the following morning.

  33. Is LDAPS required for this by chance? I’m doing it in a lab environment for testing, and do not have LDAPS configured on the Netscaler here. All the images show LDAPS being used, just making sure I’m not missing something as I troubleshoot what I did wrong (can’t login with traffic policy and auth profile added to gateway vServer, but can with them off).


    1. Microsoft AD does not allow password changes unless LDAP is encrypted. Without encryption, passwords are transmitted in clear text.

  34. Thanks Carl, all work fine. Bookmarks that i had added to “AAA Users” does not work after OTP was enabled on my Unifigateway. Any idea where i can look?

  35. Hi Carl,
    great guide! it work fine in Web Interface but when i try with Citrix Receiver it not work (username, password or passcode incorrect)… i don’t find the differences in AAA config between Web or Receiver…

    any ideas?

  36. Hi Carl, let me know how to configure LDAP advanced policy to not challenge Receiver client users and just do LDAP as nFactor authentication is not working with Receiver. With 2 LDAP policies for manage & challenge OTP, I am not able to login using Receiver as the authentication fails.

  37. Carl,

    Step 3e under Login Schemas covers how to set the correct password index value but doesn’t mention that you need to check the “Enable Single Sign On Credentials” option if you intend to pass the credentials through to RDP Hosts (at a minimum – I haven’t yet tried other services). If you don’t check this box, attempting an RDP Proxy sessions will always result in a “Connection reset by peer” error message.

  38. Hi carl, i my case Device enrollment testing is done successfully, even i can see Userparameters Attribute is also showing enrollered device list.

    But when i try it using normal login. giving error” The server met an error. Please try again or contact your administrator.

    i am using 12.0 51.24 NC build.

      1. Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[413]: receive_ldap_user_search_event 0-37: User DN= <>
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[1195]: get_otp_attribute 0-37: OTP Secret Attribute name: , length 15
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_common.c[595]: extract_ldap_attribute 0-37: retrieved UserParameters value #@Shahzad_MI=N5RM4WCYNYFE4JQU&, for shahzad
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[1195]: get_otp_attribute 0-37: OTP Secret Attribute name: , length 15
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[497]: receive_ldap_user_search_event 0-37: extracted attribute, name: UserParameters, value: #@Shahzad_MI=N5RM4WCYNYFE4JQU&,
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[1195]: get_otp_attribute 0-37: OTP Secret Attribute name: , length 15
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[514]: receive_ldap_user_search_event 0-37: For user shahzad, group stringLength 69
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[523]: receive_ldap_user_search_event 0-37: built group string for shahzad of:netscaler-admins

        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[532]: receive_ldap_user_search_event 0-37: Authentication is disabled for user shahzad, finishing ldap authentication
        Sat Aug 26 14:35:28 2017
        /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/naaad.c[2969]: send_accept 0-37: sending accept to kernel for : shahzad

  39. Hi Carl,

    Thank you for a great post on this subject.

    One thing I came across during testing of this feature, is the fact that the userParameters attribute is readable to anyone with a user account in AD, no admin rights required. And the data is not encrypted before the Netscaler stores it in AD. As a test, i copied the content of the attribute and added it to a TOTP app – Worked directly.

    So if the solution will be used in an environment where security matters also internally, another attribute should be selected and a schema extension might be required. Or the Netscaler could encrypt the content before storing it in AD (Feature request…).


    1. Hi (again). This is a followup on my own post.

      The userParameters attribute is also used to store information about the “Remote Desktop Services Profile” on the user object. Netscaler overwrites any existing attribute value when storing the token secret, and that might render a user unable to log on to a Terminal Server.

      I assume you can experience either getting a temporary profile or not been able to log on at all if temporary profiles are disabled. But you might survive if the profile location is set with GPO (not tested by me yet).

      My conclusion is that you should stay away from the userParameters attribute unless the warnings in my two posts are not a problem for you.


  40. There is a typo in the text

    LDAP Policies / Actions > 4.f >

    userParamters> = # @

    userParameters> = # @

  41. Thank you. it is very good article. I followed the steps on my lab and I was able to register my phone with Microsoft Auth and tested it just fine. the issue is that when I try to login to portal I get error” try again or contact your help desk”. also when looking at the appliance it self I see error ”
    [1245]: receive_ldap_user_search_event : ldap_first returned null, user not found
    [1245]: send_reject_with_code: Rejecting with error code 4009

    BTW, I have no group extraction setup and the user already exist in AD and I can see user parameter was created.

    Thank you in advance,


  42. Hey Carl,
    When I am in /manageotp and click ‘Go’ to try to add a device, I’m not presented with the QRCode. Click Go does nothing. Thoughts?

      1. OK, So I have a service account that does all my LDAP on the NetScaler. I have explicitly delegated permissions to the Users OU for the Service Account that applies to ‘Descendant User Objects’. The only permission that I specified was Read and Write userParameters.

        If I change the service account used by the NetScalers/LDAP to my domain admin account, OTP registration works fine.

        Are there other permissions I’ve missed on the OU?

          1. I had this same issue where device enrollment worked as long as the OTP LDAP account was domain admin, but not as a service account. I resolved with the following:
            On the Users container I applied, delegate control>>>create a custom task to delegate>>>user objects>>>property-specific>>>Read Custom Attribute 14 and Write Custom Attribute 14.
            We already use userParameters, but anything that accepts strings appears to work.

    1. In China I can see the same thing as you mentioned-QRCode is not presented,as i know the QRCode
      image is get from the“””,because China can’t access google,so i can’t get QRCode.Hope this info can help you

      1. hi Chao, yes, this QRcode issue should be general in China as you said. Have you solved this issue now? Maybe we can rewrite this google link address to China accessible QRcode provider.

  43. Hi,
    great Article, thank you Carl!

    I can register a Token but when I try to log on or test the device, I receive an error and via aaad.debug I can see “authentication is disabled for user…”.

    Temporary disabling the nextFactor helps to get logged on.

    Any Idea?

  44. Amazing post Carl! I’m no longer surprised by your skills )))

    I created all items on my environment. User can add new device, but testing procedure returns error and no added device after logoff/logon. I checked AD and attribute field still . OTP LDAP action user has access to edit these attributes.
    Could you give some advice to check if there are some mistakes plz?

    Thank you!

  45. Hi Carl, Thanks a lot for this article. By the way, microsoft authenticator can be used as well.Click on plus sign -> other (Google,…).

  46. Hi Carl,

    I just keep getting “Failed to verify OTP from Sony Z5”. I have checked your article and JGSpiers’ article thoroughly and unable to find any hints what might be wrong.

    I’m doubting I have some issues in writing the attribute userParameters in to AD as the attribute stays empty after I try adding devices and after adding the device I’m seeing the following in aaad.debug:
    /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[1195]: get_otp_attribute 0-212: OTP Secret Attribute name:
    /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_common.c[521]: extract_ldap_attribute 0-212: While retrieving ldap attributes userParameters attribute not found for kari.ruissalo
    /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[1195]: get_otp_attribute 0-212: OTP Secret Attribute name: , length 15
    /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[494]: receive_ldap_user_search_event 0-212: Failed to extract attribute, name: userParameters,
    /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[1195]: get_otp_attribute 0-212: OTP Secret Attribute name: , length 15
    /home/build/rs_120_51_22_RTM/usr.src/netscaler/aaad/ldap_drv.c[514]: receive_ldap_user_search_event 0-212: For user kari.ruissalo, group stringLength 224

    I have added my LDAP user in to Domain Admins group, so it shouldn’t be the lack of permissions here?

    Any ideas?

        1. I went through the CLI commands and spotted two differences that are now fixed (SSL-profile on GW and then the trafficaction was misconfigured for userExpression instead of passwdExpression). However, changing these values didn’t do any good.

        2. I think my issue was the LDAP actions. After I recreated them I get a confirmation in the OTP Test that it works.

          My doubts are that the service account was defined using distinguishedName and now that I changed to userPrincipalName the problem vanished.

          Great article once again Carl, thank you for your efforts!

          1. Hi kari, I am also getting the same(failed to extract attribute name:userparameter) after configuring everything. can you assist me in detail how did you manage to resolve it.

  47. Great post Carl, as usual 🙂
    Incase of using a unified gateway, It may be valuable to mention that the content switching policy need to be updated to allow users to access the “” otherwise a HTTP1.1 error will be returned to users…

    Something like this should make it work:
    is_vpn_url || HTTP.REQ.URL.CONTAINS(“/manageotp”)

    Thank you once again for a great post 🙂

      1. Hi Carl,

        Thank you for a nice guide again.

        I have been tested in my lab. I got error when I tried to verify my pin code. I already checked it that everything on AD is fill in UserProperties field. When I added my phone in this filed appear some value. But when I tired to test it, I got error: “failed to verify OTP from telefon”. In previous step I just added my phone as “telefon”.

        Could please give me some advice where is my issue?

        PS: In Google Authenticator showed me my account as, which domain is wrong one. My lab is located in domain

        Thank you!


        1. Hello Carl,

          I would you like to add in something here. I have tested and found this from ns.log:

          Sep 19 17:32:10 x.x.x.x 09/19/2017:14:32:10 GMT nsvpx12-01 0-PPE-0 : default AAA Message 35950 0 : “(0-222) send_authenticate_pdu_withconf: Sending Preamble”
          Sep 19 17:32:10 x.x.x.x 09/19/2017:14:32:10 GMT nsvpx12-01 0-PPE-0 : default AAA Message 35951 0 : “(0-222): sslvpn_manage_otp_handler: Reply Received, status from aaad: 2”
          Sep 19 17:32:10 x.x.x.x 09/19/2017:14:32:10 GMT nsvpx12-01 0-PPE-0 : default SSLVPN Message 35953 0 : “Failed to verify incoming OTP value 378195 for user: ………”

          Thank you for helping to find the issue.


          1. adding more info:

            root@# nsconmsg -g otp -d stats
            Displaying current counter value information
            NetScaler V20 Performance Data
            NetScaler NS12.0: Build, Date: Aug 25 2017, 11:23:59

            reltime:mili second between two records Tue Sep 19 17:49:59 2017
            Index reltime counter-value symbol-name&device-no
            1 1178461 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 27 aaa_otp_tot_verify_fail
            11 0 47 aaa_otp_tot_manage_success
            13 0 1 aaa_otp_tot_manage_fail
            15 0 0 dns_totpipelined_request

            I can enroll my phone successfully to my account, but verification is not working.

            Thank you!

        2. Make sure the service account that you are using for LDAP has read and write permissions in Active Directory.

Leave a Reply

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