NetScaler nFactor authentication – Google reCAPTCHA first factor LDAP second – Citrix ADC 12.1.49.37 and below

Integrating reCAPTCHA by Google with Citrix NetScaler is a great move towards protecting internal resources from attackers. If someone or even a bot of computers are trying to brute force an account, or break in to your system, having reCAPTCHA is sure to defer such activies and make it a very difficult task to achieve.

Note: This article describes the methods to configure reCaptcha on Citrix ADC running firmware version 12.1 build 49.37 or below. For methods on newer builds, see here.

In this post, I’ll describe how you can place reCAPTCHA in the first line of authentication with WebAuth, and LDAP as the second factor. This is all using nFactor for NetScaler Unified Gateway which was released in versions 11.1. I’ve previously described how you can use RADIUS, LDAP and Azure authentication technologies with nFactor to create a dynamic real-time authentication system. You can read more about that here https://jgspiers.com/nfactor-authentication-with-netscaler-gateway/

To begin integrating reCAPTCHA with NetScaler, you first need to sign up to the free service https://www.google.com/recaptcha/admin

Select reCATPCHA V2. Specify a descriptive label and enter your domain name which will be the FQDN of NetScaler Gateway.

Note: Invisible reCAPTCHA has not been released for GA so do not choose this.

Agree to the ToS and click Register.

You’ll be given a Site key and Secret key. Keep these secure and safe, you’ll need them later.

Log on to NetScaler using a program such as WinSCP and create a new Login Schema file. This file will generate the UI users see when logging on to NetScaler, containing the reCAPTCHA box and a username field. The username is extracted and placed in the next Login Schema for LDAP authentication. Login Schemas that you create should reside in /nsconfig/loginschema/.

The XML code you need is here, take a copy:

<?xml version="1.0" encoding="UTF-8"?>
<AuthenticateResponse xmlns="http://citrix.com/authentication/response/1">
<Status>success</Status>
<Result>more-info</Result>
<StateContext></StateContext>
<AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack>
<CancelPostBack>/nf/auth/doLogoff.do</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
<Requirements>
<Requirement><Credential><ID>login</ID><SaveID>ExplicitForms-Username</SaveID><Type>username</Type></Credential><Label><Text>User name:</Text><Type>plain</Type></Label><Input><AssistiveText>Please supply either domain\username or user@fully.qualified.domain</AssistiveText><Text><Secret>false</Secret><ReadOnly>false</ReadOnly><InitialValue></InitialValue><Constraint>.+</Constraint></Text></Input></Requirement>
<Requirement><Credential><ID>saveCredentials</ID><Type>savecredentials</Type></Credential><Label><Text>Remember my password</Text><Type>plain</Type></Label><Input><CheckBox><InitialValue>false</InitialValue></CheckBox></Input></Requirement>
<Requirement><Credential><ID>nf-recaptcha</ID><SaveID>ExplicitForms-Username</SaveID><Type>nf-recaptcha</Type></Credential><Label><Text>Captcha:</Text><Type>plain</Type></Label></Requirement>
<Requirement><Credential><Type>none</Type></Credential><Label><Text>Please enter your username and verify captcha</Text><Type>information</Type></Label><Input /></Requirement>
<Requirement><Credential><ID>loginBtn</ID><Type>none</Type></Credential><Label><Type>none</Type></Label><Input><Button>Log On</Button></Input></Requirement>
</Requirements>
</AuthenticationRequirements>
</AuthenticateResponse>

Now add a Login Schema Profile to NetScaler. Log on to the GUI, navigate to Security -> AAA – Application Traffic -> Login Schema -> Profiles -> Add.

Specify an appropriate name and click on the edit button under noschema.

Select the Google Captcha Login Schema. Click Select.

Click Create.

Next create a Login Schema Policy. Click the Policies tab -> Add.

Specify an appropriate name, under Profile choose the Login Schema Profile you created. Under Rule enter true. Click Create.

Edit your AAA vServer and bind the Login Schema directly to this server. I’m assuming you have already created the AAA vServer, Authentication Profile and other parks to use nFactor. If you have not, use the link at the top of this post for guidance. This Login Schema will now apply to all users logging on to my NetScaler. This is the first schema/UI that will be shown to users.

We need another Login Schema, this is for the second factor using LDAP. The Login Schema contains a username and password box, however the username is extracted from the previous WebAuth/reCAPTCHA schema. Create a new Login Schema file as below.

The XML code you need is here, take a copy:

<?xml version="1.0" encoding="UTF-8"?><AuthenticateResponse xmlns="http://citrix.com/authentication/response/1"><Status>success</Status><Result>more-info</Result><StateContext /><AuthenticationRequirements>
<PostBack>/nf/auth/doAuthentication.do</PostBack><CancelPostBack>/Citrix/Authentication/ExplicitForms/CancelAuthenticate</CancelPostBack><CancelButtonText>Cancel</CancelButtonText>
<Requirements><Requirement><Credential><ID>login</ID><SaveID>ExplicitForms-Username</SaveID><Type>username</Type></Credential><Label><Text>Username</Text><Type>plain</Type></Label><Input><AssistiveText>Please supply either domain\username or user@fully.qualified.domain</AssistiveText><Text><Secret>false</Secret><ReadOnly>true</ReadOnly><InitialValue>${HTTP.REQ.USER.NAME}</InitialValue><Constraint>.+</Constraint></Text></Input></Requirement><Requirement><Credential><ID>passwd</ID><SaveID>ExplicitForms-Password</SaveID><Type>password</Type></Credential><Label><Text>Password:</Text><Type>plain</Type></Label><Input><Text><Secret>true</Secret><ReadOnly>false</ReadOnly><InitialValue/><Constraint>.+</Constraint></Text></Input></Requirement>
<Requirement><Credential><Type>none</Type></Credential><Label><Text>Please enter your password</Text><Type>confirmation</Type></Label><Input /></Requirement>
<Requirement><Credential><ID>saveCredentials</ID><Type>savecredentials</Type></Credential><Label><Text>Remember my password</Text><Type>plain</Type></Label><Input><CheckBox>
<InitialValue>false</InitialValue></CheckBox></Input></Requirement><Requirement><Credential><ID>loginBtn</ID><Type>none</Type></Credential><Label><Type>none</Type></Label><Input><Button>Log On</Button></Input></Requirement></Requirements></AuthenticationRequirements>
</AuthenticateResponse>

Create another Login Schema Profile for the username extraction piece as shown below, using the XML file you created. You don’t need to create a Login Schema Policy.

Next create a Policy Label for the second LDAP factor. Navigate to Security -> AAA – Application Traffic -> Policies -> Authentication -> Advanced Policies -> Authentication Policy Labels -> Add.

Enter a name, under Login Schema choose the Username Extract Login Schema you just created. Click Continue.

Click on Click to select under Select Policy.

Bind your LDAP policy, if you don’t have one, create one first. Click Select.

Under Goto Expression select END. No other factors will be used. Click Bind.

Click Done.

Next using WinSCP or similar, navigate to var/netscaler/logon/LogonPoint/custom on NetScaler. Edit the script.js file and enter the following JavaScript code:

Note: Replace the key beside var reCaptchaSiteKey = with your own Site key.

/*
* Custom credential handler for Google ReCaptcha.
* If a credential of type "nf-recaptcha" is sent in any factor, this code
* will be executed. The "submit" button of the form will be disabled
* by default until the CAPTCHA is completed correctly.
*
* Use with the below WebAuth action:
* add authentication webAuthAction recaptcha -serverIP <IP Address of google.com> -serverPort 443 -fullReqExpr q{"POST /recaptcha/api/siteverify HTTP/1.1\r\n" + "Host: www.google.com\r\n" + "Content-Type: applica
tion/x-www-form-urlencoded\r\n" + "Content-Length: 10000"+"\r\n\r\n" + "secret=<Secret key from Google Recaptcha>&response=" + http.req.body(10000).after_str("&recaptcha=")} -scheme https -successRule "http.RES.body(1000).REGEX_MATCH(re/
\"success\": true.*\"hostname\": \"<FQDN of the Gateway/Auth vServer>\"/)"
*
*/
CTXS.ExtensionAPI.addCustomCredentialHandler({
                  getCredentialTypeName: function () { return "nf-recaptcha"; },

                  getCredentialTypeMarkup: function (requirements) {
                                    var reCaptchaSiteKey = "6LfAtxoUAAAAAKaGJY2RO7QGLBM8BRcQDf5dACaG"; //Replace this with the SiteKey from Google ReCaptcha
                                    var div = $("<div></div>");
                                    var CAPTCHA = $('<div id="g-recaptcha" class="g-recaptcha" data-callback="captchaSuccess"></div>').attr("data-sitekey", reCaptchaSiteKey);
                                    var input = $('<input id="captchaResponse" name="recaptcha" type="hidden" value=""/>');
                                    div.append(CAPTCHA, input);
                                    var script = document.createElement("script");
                                    script.type = "text/javascript";
                                    script.src = "https://www.google.com/recaptcha/api.js";
                                    script.onerror = function(){
                                                      var $form = $(".credentialform")[0];
                                                      var fieldDiv = $('<div class="field CredentialTypenone"></div>');
                                                      var leftDiv = $('<div class="left"></div>');
                                                      var label = $('<div class="standaloneText label error" role="alert"></div>').text("Could not load Google ReCaptcha. Please contact your administrator.");
                                                      leftDiv.append(label);
                                                      fieldDiv.append(leftDiv);
                                                      $($form).append(fieldDiv);
                                    };
                                    $("head")[0].appendChild(script);

                                    $(document).on('ctxsformsauthenticationdisplayform', function (e, data) {
                                                      var $form = data.authenticationElement.find('.credentialform');
                                                      var $CAPTCHA = $form.find('#g-recaptcha');
                                                      $loginButton = $form.find('#loginBtn');
                                                      if ($CAPTCHA.length && $loginButton.length) {
                                                                        // This is a CAPTCHA form
                                                                        // Disable the submit button by default
                                                                        disableFormsButton($loginButton);
                                                      }
                                    });

                                    return div;
                  }
});
/* End ReCaptcha code */

var $loginButton;
function captchaSuccess(data) {
        $("#captchaResponse").val(data);
        enableFormsButton($loginButton);
}

function disableFormsButton($button) {
        // Disable the button and stop it appearing clickable
        $button.addClass('disabled').removeAttr('href');
}
function enableFormsButton($button) {
        // Enable the button and make it clickable again
        $button.removeClass('disabled').attr('href', '#');
}

Navigate to Security -> AAA – Application Traffic -> Policies -> Authentication -> Basic Policies -> WEB -> Servers -> Add. The Web Auth policy is used for reCAPTCHA verification with Google.

Enter an appropriate name, the Web Server IP Address should resolve to google.com. The Port/Protocol should be 443 and HTTPS. In the HTTP Request Expression field, secret= should match your Site secret provided by Google. Under Expression to validate the Authentication change the hostname to your NetScaler Gateway FQDN. Click Create.

Now navigate to Security -> AAA – Application Trafic -> Policies -> Authentication -> Advanced Policies -> Authentication Policies -> Add.

Enter an appropriate name. Under Action Type choose WEBAUTH. Under Action choose the WebAuth server you just created. Enter true under Expression. Click Create.

Navigate back to the AAA vServer and add a new Authentication Policy.

Select the Web Auth policy as first factor, choose the LDAP Only/Username Extracted Policy Label for Next Factor. Click Bind.

Your Authentication Policy should look like this. It’s time to test it out.

When navigating to NetScaler Gateway, the first Login Schema CaptchaLoginSchema displays with a username and captcha field. Enter your username and then tick I’m not a robot.

You will be challenged to select a number of specific pictures, in my case, there was nothing to select so I clicked SKIP.

Next I was challenged to select all squares with a street sign. Click VERIFY.

Captcha verification is complete and you’ll be able to continue to the next factor. Click Log On. At this stage, the username you entered will be captured and fed through to next factor. You could in theory do something such as Group Extraction or other methods and apply many different factors based on who the user is.

In my case, I’m only selecting LDAP. Notice the second Username Extract Login Schema now shows, with my username extracted from previous factor. Enter password and click Log On.

Log on to Unified Gateway is successful.


19 Comments

  • Pingback: EUC Weekly Digest – April 1, 2017 – Carl Stalhood

  • Pingback: Detailed Change Log – Carl Stalhood

  • Pingback: nFactor Authentication for NetScaler Gateway 11.1 – Carl Stalhood

  • Alessio

    April 27, 2017

    HI there, amazing walkthrough! Yet when I configured this it gets stuck when I try to log on after verifying the captcha. It doesn’t take me to the next LDAP authentication, can you help me?
    I always get this javascript error : “ctxs.webui.min.js:249 ctxsFormsAuthentication:could not parse Input node”

    Reply
  • George Spiers

    April 27, 2017

    What version of NetScaler? Send a screenshot of the error to george@jgspiers.com

    Reply
    • Alessio

      April 27, 2017

      NetScaler 11.1 53.11.nc. I’ll send you the screenshot right away

      Reply
  • Pingback: nFactor Authentication for NetScaler Gateway 12 – Carl Stalhood

  • Pingback: nFactor authentication with NetScaler Unified Gateway | Peter Bats

  • Alexandre

    September 5, 2018

    Hello,

    It’s ok for a web auth, but for the heavy client, how do you do ?

    Reply
    • George Spiers

      September 5, 2018

      Not supported yet for Receiver or Workspace app.

      Reply
    • George Spiers

      October 23, 2018

      It is now supported on Workspace app for Windows 1809, using Gateway 12.1.49.x, should also work on Workspace app for Mac.

      Reply
  • Pingback: nFactor Authentication – NetScaler Gateway 12 / Citrix Gateway 12.1 – Carl Stalhood

  • Pingback: nFactor Authentication – Citrix Gateway 13 – Carl Stalhood

  • Sascha Driemel

    April 3, 2020

    Hi,
    is it possible to apply the recaptcha only to a single vServer and not automatically to all vServers on the netscaler. We have currently a bunch of vServers using ldap and radius authentication and now we have a request to provide recaptcha and ldap for a single vServer

    Reply
    • George Spiers

      May 22, 2020

      Yes just bind the Authentication Profile to your particular vServer.

      Reply
  • Radix

    April 19, 2020

    Hi!
    Thanks for this document! Following every step, when I configured this it gets stuck when must show google captcha field (box to mark), it does not appear. On web browser with F11 and console, I am getting this message: “Uncaught Error: Missing required parameters: sitekey at new dz (recaptcha__es.js:272)” but site key is already at file script.js. Can you help me on this? We are running Netscaler vpX 200 version 12.0.63.13

    Reply
    • Radix

      April 20, 2020

      Sorry, We have found other document to inferior netscaler version, applying one of them we have solved this question: SOLVED BY CTX216091: In latest versions of NetScaler, a new script /var/netscaler/logon/LogonPoint/plugins/ns-gateway/ns-nfactor.js already has the required code ‘sitekey ‘ for running re-CAPTCHA.

      Thanks!

      Reply
  • Anonymous

    August 6, 2020

    Hello

    needed your help. I have followed this article to every letter. Point is that client wants to use LDAP as first factor, and use RSA/ azure MFA nps based on group. They want to eventually move away from RSA and move to NPS.

    https://blog.markdepalma.com/?p=411

    i have made the login schemas, policies, POLICY label, AAA server and i am on the login page now for AAA virtual server. LDAP credentials are accepted, and it moves on to either RSA ( based on group) or MFA NPS azure. The end user is able to get the Radius codes for both (RSA and NPS), however when the user puts in the code, the error event ID number 10 comes in Citrix Receiver for Web ( Cannot complete your request) .

    Note: it is able to communicate with NPS and it is getting the code, and RSA, but when we put in the code.. it says Cannot complete your request(NPS), and for RSA( it says contact your help desk invalid code).

    any thoughts?

    followed this article to the letter:

    https://blog.markdepalma.com/?p=411

    Reply

Leave a Reply to Alessio Cancel reply