Jump to content
Updated Privacy Statement

Juliano Reckziegel

Authors
  • Posts

    5
  • Joined

  • Last visited

Recent Profile Visitors

197 profile views

Juliano Reckziegel's Achievements

Rookie

Rookie (2/14)

  • One Year In
  • First Post Rare
  • Conversation Starter Rare
  • Week One Done
  • One Month Later

Recent Badges

0

Reputation

  1. Hi Scott I am glad you were able to implement this solution. Evaluate DUO first was intentional to protect the user account against locks attacks. You can invert the authentication flow, but you will need to restructure the the authentication logic and edit the XML and script.js files as followed: XML: Change the following lines: <Credential><ID>passwd1</ID><SaveID>passwd1</SaveID><Type>password</Type></Credential> .. <Credential><ID>passwd</ID><SaveID>passwd</SaveID><Type>duoselector</Type></Credential> to: <Credential><ID>passwd</ID><SaveID>passwd</SaveID><Type>password</Type></Credential> .. <Credential><ID>passwd1</ID><SaveID>passwd1</SaveID><Type>duoselector</Type></Credential> script.js Change the following lines btbase.attr("name","passwd"); to: btbase.attr("name","passwd1"); I hope this helps you. Best Regards
  2. This occurs because DUO responds with a RADIUS REJECT instead of a RADIUS CHALLENGE. Perhaps consulting a DUO SME could help determine if there's a configuration option in the DUO proxy to alter this behavior.
  3. [UPDATE February 23, 2024] It has come to our attention that leveraging client IP information in DUO allows for the application of distinct policies, a feature previously overlooked in our integration. Specifically, we had failed to transmit this information to the DUO proxy server, thereby preventing the implementation of such policies. By default, DUO utilizes the RADIUS calling-station-id attribute as the client IP. In response, I have updated the NetScaler RADIUS action to include this attribute, ensuring that the client IP information is now accurately passed to the DUO proxy server. This enhancement enables the effective utilization of client IP data for policy application within DUO. As Cisco DUO's iframe integration reaches its end of support on September 30, 2024, organizations must transition to DUO Universal Prompt or adopt a RADIUS configuration without the iframe for continued support. In this article, we explore how to utilize the NetScaler nFactor framework to replicate the iframe functionality while leveraging the non-iframe RADIUS integration, ensuring a smooth transition for users and administrators alike. User Experience Overview: The integration facilitates a seamless user experience, ensuring secure authentication while maintaining convenience. Users are presented with a familiar interface where they can select authentication methods such as DUO Push, SMS, phone call, or passcode entry, ensuring flexibility and accessibility. The following image, depict the user experience using this integration method: How this works In addition to passcodes, DUO has special words that can be sent via RADIUS to the DUO proxy server that will trigger actions as followed: push: Sends a push notification to the user's device. sms: Sends an SMS with passcodes to the user's device. phone: Initiates a phone call to the user's device for confirmation. push#: Sends a push notification to the specified device (e.g., push2 for the second device). sms#: Sends an SMS with passcodes to the specified device (e.g., sms3 for the third device). phone#: Initiates a phone call to the specified device for confirmation (e.g., phone2 for the second device). NetScaler communicates with the DUO proxy server by sending the appropriate keyword based on the user's selection: push: When the DUO Push option is selected. passcode: When the user enters a passcode. sms: When the Send SMS option is chosen. phone: When the Call Phone option is selected. Users can manually select the passcode option and input special keywords (e.g., push2, phone3, sms4) to authenticate with alternative devices. Authentication Flow The authentication flow is configured with two factors: DUO MFA via RADIUS: The first factor verifies the user's MFA against DUO via RADIUS. LDAP Password: The second factor authenticates the user's password via LDAP. This sequential configuration helps to prevent that Active Directory (AD) accounts are locked due to excessive authentication attempts. DUO Configuration On the DUO proxy configuration file (authproxy.cfg), make sure you have a client session with [duo_only_client] defined and create a new radius_server_duo_only entry on a port that is available, make sure to add the NSIP of both HA pair nodes and SNIP as RADIUS clients as needed. [duo_only_client] [radius_server_duo_only99] api_host=api-XXXXXXXX.duosecurity.com ikey=XXXXXXXXXXXXXXXXXXXX skey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX failmode=safe radius_ip_1=192.168.0.100 radius_secret_1=RADIUS_SECRET_123 radius_ip_2=192.168.0.151 radius_secret_2=RADIUS_SECRET_123 radius_ip_3=192.168.0.152 radius_secret_3=RADIUS_SECRET_123 port=18128 Use this configuration as a reference for setting up the DUO proxy server in your environment. Make sure to adapt the settings to match your specific setup, including any changes in IP addresses, shared secrets, or port numbers. If further assistance is required, consult the DUO support documentation or reach out to their support team for guidance on configuring a new radius_server_duo_only session on the authproxy.cfg file. NetScaler Configuration Assuming that the Citrix Gateway virtual server is already provisioned with necessary configurations such as certificates, Secure Ticket Authority (STA) servers, and session policies/profiles, follow these additional steps to integrate Cisco DUO using the nFactor extensibility features: Disable Single Sign-on Domain: Ensure that the "Single Sign-on Domain" is disabled on the session profile. This step is crucial for passing the UserPrincipalName to StoreFront. nFactor Extensibility Features: Utilize the nFactor extensibility features to customize the authentication process and integrate Cisco DUO options seamlessly. This involves creating a new XML Schema and adding jQuery code to the portal theme scripts.js file. XML schema Create a new xml file called duo.xml located at /nsconfig/loginschema with the following content: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AuthenticateResponse xmlns="http://citrix.com/authentication/response/1"> <Status>success</Status> <Result>more-info</Result> <StateContext/> <AuthenticationRequirements> <PostBack>/nf/auth/doAuthentication.do</PostBack> <CancelPostBack>/nf/auth/doLogoff.do</CancelPostBack> <CancelButtonText>Cancel</CancelButtonText> <Requirements> <Requirement> <Credential><Type>none</Type></Credential> <Label><Text>dualauth_please_log_on</Text><Type>nsg-login-label</Type></Label> <Input/> </Requirement> <Requirement> <Credential><ID>login</ID><SaveID>login</SaveID><Type>username</Type></Credential> <Label><Text>dualauth_user_name</Text><Type>nsg-login-label</Type></Label> <Input><Text><ReadOnly>false</ReadOnly><InitialValue/><Constraint>.+</Constraint></Text></Input> </Requirement> <Requirement> <Credential><ID>passwd1</ID><SaveID>passwd1</SaveID><Type>password</Type></Credential> <Label><Text>dualauth_password</Text><Type>nsg-login-label</Type></Label> <Input><Text><Secret>true</Secret><Constraint>.+</Constraint></Text></Input> </Requirement> <Requirement> <Credential><ID>passwd2</ID><Type>duopasscode</Type></Credential> <Label><Text>dualauth_passcode</Text><Type>nsg-login-label</Type></Label> <Input/><!-- input field generated by custom handler --> </Requirement> <Requirement> <Credential><ID>passwd</ID><SaveID>passwd</SaveID><Type>duoselector</Type></Credential> <Label><Type>none</Type></Label> <Input/><!-- radio buttons created by custom handler --> </Requirement> <Requirement> <Credential><Type>duoinfotext</Type></Credential> <Label><Type>none</Type></Label> <Input/><!-- information message from custom handler --> </Requirement> <Requirement> <Credential><ID>Logon</ID><Type>none</Type></Credential> <Label><Type>none</Type></Label> <Input><Button>dualauth_submit</Button></Input> </Requirement> </Requirements> </AuthenticationRequirements> </AuthenticateResponse> Portal Theme Create a new portal theme called RfWebUI_DUO with the following NetScaler command: add vpn portaltheme RfWebUI_DUO -basetheme RfWebUI Add the following content to /var/netscaler/logon/themes/RfWebUI_DUO/script.js file: // This function creates the passcode field for Duo CTXS.ExtensionAPI.addCustomCredentialHandler({ // Credential type defined in login schema getCredentialTypeName: function() { return "duopasscode"; }, // Generate HTML for the custom credential getCredentialTypeMarkup: function(requirements) { var input = $("<input>"); input.attr("id","passwd2"); input.attr("name","passwd2"); //input.attr("type","password"); input.attr("type","text"); input.attr("autocomplete","off"); input.attr("spellcheck","false"); input.prop("disabled",true); input.on("change",function(){$("#duocode").attr("value",$("#passwd2").val());}); return input; } }); // This function creates the radio buttons for Duo CTXS.ExtensionAPI.addCustomCredentialHandler({ // Credential type defined in login schema getCredentialTypeName: function() { return "duoselector"; }, // Generate HTML for the custom credential getCredentialTypeMarkup: function(requirements) { var table = $("<table></table>"); table.addClass("radioButtons"); table.css("border-spacing",0); table.css("height",44); var tr = $("<tr></tr>"); tr.appendTo(table); var tdbase = $("<td></td>"); tdbase.css("width","25%"); var btbase = $("<input>"); btbase.attr("type","radio"); btbase.attr("name","passwd"); var lbbase = $("<label></label>"); lbbase.css("font-size","12px"); lbbase.css("color","#999999"); var button = btbase.clone(); button.attr("value","push"); button.attr("id","duopush"); var label = lbbase.clone(); label.attr("for","duopush"); label.text(" Duo Push"); var td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",true)}); button.prop("checked","checked"); button = btbase.clone(); button.attr("value","code"); button.attr("id","duocode"); label = lbbase.clone(); label.attr("for","duocode"); label.text(" Passcode"); td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",false)}); button = btbase.clone(); button.attr("value","sms"); button.attr("id","duotext"); label = lbbase.clone(); label.attr("for","duotext"); label.text(" Send SMS"); td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",true)}); button = btbase.clone(); button.attr("value","phone"); button.attr("id","duocall"); label = lbbase.clone(); label.attr("for","duocall"); label.text(" Call Phone"); td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",true)}); return table; } }); // This function creates the information text for Duo CTXS.ExtensionAPI.addCustomCredentialHandler({ // Credential type defined in login schema getCredentialTypeName: function() { return "duoinfotext"; }, // Generate HTML for the custom credential getCredentialTypeMarkup: function(requirements) { var link = $("<a>here</a>"); link.attr("href","https://support.fqdn.com.lab"); link.attr("target","_blank"); link.css("color","#02a1c1"); var div = $("<div></div>"); div.css("width",385); div.css("font-size","12px"); div.css("color","#999999"); div.css("text-align","center"); div.append("Click ",link," if you are not enrolled in Duo."); div.append("<br>","For assistance call the Help Desk, (XXX) XXX-XXXX."); return div; } }); NetScaler commands To the nFactor flow on NetScaler, you would use a series of CLI commands. Below are the commands to put together the configuration for integrating Cisco DUO using nFactor extensibility features and enabling/disabling the passcode field: Login Schema add authentication loginSchema DUO_LS -authenticationSchema "/nsconfig/loginschema/duo.xml" add authentication loginSchemaPolicy DUO_LSPOL -rule TRUE -action DUO_LS RADIUS policy/action In this particular step, the authTimeout is set to 60 seconds. This duration allows users a window of up to one minute to respond to authentication prompts such as push notifications or phone calls. Adjusting the authTimeout value provides flexibility in accommodating user response times within the nFactor authentication flow. The callingstationid parameter is used to pass the user source IP to the DUO proxy server. add authentication radiusAction DUO_SRV -serverIP 192.168.0.51 -serverPort 18128 -authTimeout 60 -radKey RADIUS_SECRET_123 -callingstationid ENABLED add authentication Policy DUO_POL -rule TRUE -action DUO_SRV LDAP policy/action In this step, the ssoNameAttribute parameter is configured to specify the userPrincipalName. As a result, there's no need to explicitly specify the Single Sign-on Domain on the session policy. This configuration streamlines the authentication process by automatically utilizing the userPrincipalName attribute for Single Sign-on purposes without additional policy settings. add authentication ldapAction LDAP_SRV -serverIP 192.168.0.5 -serverPort 636 -ldapBase "dc=company,dc=lab" -ldapBindDn serviceaccount@company.lab -ldapBindDnPassword SERVICE_ACCOUNT_PASSWORD -ldapLoginName sAMAccountName -groupAttrName memberOf -subAttributeName cn -secType SSL -ssoNameAttribute userprincipalname -passwdChange ENABLED add authentication Policy LDAP_POL -rule TRUE -action LDAP_SRV Policy Label This policy label represents the second factor of the authentication flow. add authentication policylabel LDAP_PL_noschema -loginSchema LSCHEMA_INT bind authentication policylabel LDAP_PL_noschema -policyName LDAP_POL -priority 100 -gotoPriorityExpression NEXT Authentication logic This authentication logic is implemented on an authentication virtual server. add authentication vserver DUO_AAA SSL 0.0.0.0 bind authentication vserver DUO_AAA -policy DUO_LSPOL -priority 100 -gotoPriorityExpression END bind authentication vserver DUO_AAA -policy DUO_POL -priority 100 -nextFactor LDAP_PL_noschema -gotoPriorityExpression NEXT bind ssl vserver DUO_AAA -certkeyName Sample01_SAN The last command in this block binds a certificate to the authentication virtual server. This step is optional and primarily serves to display the virtual server in an UP (operational) state. Authentication Profile The authentication profile is used to link the authentication virtual server with a Citrix Gateway virtual server. add authentication authnProfile DUO_AuthProf -authnVsName DUO_AAA Citrix Gateway configuration As mentioned previously, we are considering and pre-existing Citrix Gateway virtual server, in this case it is called "gw214.company.lab DUO". The following command will link it to the authentication logic: set vpn vserver "gw214.company.lab DUO" -authnProfile DUO_AuthProf The following command binds the new RfWebUI theme to the Citrix Gateway virtual server. bind vpn vserver "gw214.company.lab DUO" -portaltheme RfWebUI_DUO No SMS option If your organization deems SMS as an unsuitable MFA method, you have the option to disable it within the authentication interface. This can be accomplished by adjusting the script.js file. To implement this change, follow these steps: Modify the width of the table cell (td) to 33% to accommodate the remaining authentication options effectively. Comment out the section of the code responsible for generating the SMS option. By making these adjustments, the SMS option will no longer be displayed within the authentication interface, ensuring that only the preferred MFA methods are presented to users during authentication. // This function creates the passcode field for Duo CTXS.ExtensionAPI.addCustomCredentialHandler({ // Credential type defined in login schema getCredentialTypeName: function() { return "duopasscode"; }, // Generate HTML for the custom credential getCredentialTypeMarkup: function(requirements) { var input = $("<input>"); input.attr("id","passwd2"); input.attr("name","passwd2"); //input.attr("type","password"); input.attr("type","text"); input.attr("autocomplete","off"); input.attr("spellcheck","false"); input.prop("disabled",true); input.on("change",function(){$("#duocode").attr("value",$("#passwd2").val());}); return input; } }); // This function creates the radio buttons for Duo CTXS.ExtensionAPI.addCustomCredentialHandler({ // Credential type defined in login schema getCredentialTypeName: function() { return "duoselector"; }, // Generate HTML for the custom credential getCredentialTypeMarkup: function(requirements) { var table = $("<table></table>"); table.addClass("radioButtons"); table.css("border-spacing",0); table.css("height",44); var tr = $("<tr></tr>"); tr.appendTo(table); var tdbase = $("<td></td>"); // tdbase.css("width","25%"); tdbase.css("width","33%"); var btbase = $("<input>"); btbase.attr("type","radio"); btbase.attr("name","passwd"); var lbbase = $("<label></label>"); lbbase.css("font-size","12px"); lbbase.css("color","#999999"); var button = btbase.clone(); button.attr("value","push"); button.attr("id","duopush"); var label = lbbase.clone(); label.attr("for","duopush"); label.text(" Duo Push"); var td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",true)}); button.prop("checked","checked"); button = btbase.clone(); button.attr("value","code"); button.attr("id","duocode"); label = lbbase.clone(); label.attr("for","duocode"); label.text(" Passcode"); td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",false)}); // button = btbase.clone(); // button.attr("value","sms"); // button.attr("id","duotext"); // label = lbbase.clone(); // label.attr("for","duotext"); // label.text(" Send SMS"); // td = tdbase.clone(); // td.append(button,label); // td.appendTo(tr); // button.on("change",function(){$("#passwd2").prop("disabled",true)}); button = btbase.clone(); button.attr("value","phone"); button.attr("id","duocall"); label = lbbase.clone(); label.attr("for","duocall"); label.text(" Call Phone"); td = tdbase.clone(); td.append(button,label); td.appendTo(tr); button.on("change",function(){$("#passwd2").prop("disabled",true)}); return table; } }); // This function creates the information text for Duo CTXS.ExtensionAPI.addCustomCredentialHandler({ // Credential type defined in login schema getCredentialTypeName: function() { return "duoinfotext"; }, // Generate HTML for the custom credential getCredentialTypeMarkup: function(requirements) { var link = $("<a>here</a>"); link.attr("href","https://support.fqdn.com.lab"); link.attr("target","_blank"); link.css("color","#02a1c1"); var div = $("<div></div>"); div.css("width",385); div.css("font-size","12px"); div.css("color","#999999"); div.css("text-align","center"); div.append("Click ",link," if you are not enrolled in Duo."); div.append("<br>","For assistance call the Help Desk, (XXX) XXX-XXXX."); return div; } }); Conclusion In conclusion, this article highlights the versatility of NetScaler nFactor in addressing the imminent discontinuation of the DUO iframe integration. By leveraging nFactor's capabilities, organizations can seamlessly transition to alternative authentication methods while maintaining security and a similar user experience. In this article, I've demonstrated a direct connection to the DUO RADIUS proxy and LDAP servers for simplicity. However, as a best practice, it's recommended to implement a load balancing virtual server for these components. This approach enhances the reliability and availability of the authentication infrastructure, ensuring seamless operation even in the event of server failures or high traffic loads. It's worth noting that users with multiple devices can conveniently authenticate by selecting the passcode option and inputting special keywords such as push#, sms#, phone# followed by the device number. For example, entering push2 will trigger a push notification to the user's second registered device. Credit for the original engineering of this solution goes to my former colleague, Edson da Luz, in 2021. I've made minor updates to present it here. Kudos to Edson for his creativity and skill in implementing this logic. This article serves as a testament to the adaptability and innovation within the cybersecurity landscape, offering practical solutions to evolving challenges in authentication and access management.
  4. Previously, we explored customizing the Citrix Gateway authentication page via JavaScript, offering extensive flexibility, as detailed in a prior article. However, a recent scenario arose where a customer sought minor visual alterations to the login form. To accomplished this we used simple CSS instructions. The desired changes were straightforward: Relocate the form header to the top of the username input field and make it bold. Adjust the positioning of the "User name:" and "Password:" labels nearer to the input fields. The initial authentication page resembled the left part of the following image, while the right side view reflected the desired modifications: To implement this, we created a new RfWebUI theme and edited the initially empty style.css file situated at /var/netscaler/logon/themes/NAME_OF_YOUR_NEW_RfWebUI_THEME/ with the following content: @media (min-width: 610px) { #login_title { margin-left: 186px; font-weight: bold; } .credentialform .plain { display: block; width: 175px; text-align: right; height: 44px; margin: 0; } } The @media rule, utilized in media queries, facilitates applying distinct styles for varying media types or devices. This ensures that the browser implements these configurations solely when the screen width is at least 610px, preventing formatting issues on mobile devices. The first section targets the element identified by the ID 'login_title', representing the form title. You can verify this through browser developer tools: The subsequent section modifies elements containing the CSS classes 'credentialform' and 'plain', as depicted in the following image: Remember, NetScaler caches Gateway files within its internal optimization cache, irrespective of whether the IC feature is active or not. To purge cached objects from the NetScaler, execute the following command: flush contentGroup loginstaticobjects An important aspect to note is that these customizations endure NetScaler reboots and upgrades. This method empowers you to effect minor or significant updates in how this page displays. Consider this as a reference for potential modifications, allowing ample creativity in customization.
  5. In numerous instances, there's a need to customize the Citrix Gateway login page. Sometimes, it's crucial to include disclaimers, while in other cases, it's essential to direct users to a support link, among other requirements. It has come to our attention that many companies have attempted to modify the built-in HTML/JS files for this purpose. However, this approach is neither supported nor sustainable because these customizations can be lost during system upgrades or even routine reboots, unless you utilize the 'rc.netscaler' file. An alternative method is to employ rewrite policies or use a JavaScript file within a customized RfWebUI theme. These approaches ensure that your customizations persist through system reboots and upgrades, making them the preferred choice. Personally, I prefer employing a JavaScript file because it's compatible with both Citrix Gateway virtual servers and AAA virtual servers, providing a remarkable level of versatility. This is primarily due to its ability to inject HTML code either before, after, or within specific elements or their parent elements. All that's required is the identification of a class name or an ID on the webpage to instruct the browser to insert extra elements precisely at that location. Below is an example of a Citrix Gateway landing page with text additions incorporated into an RfWebUI theme without a logo." Additionally, these types of objects are also cached by the end user's browser. Consequently, if you wish to modify messages and immediately see the changes, you'll need to clear both the NetScaler cache and the browser cache. To clear the NetScaler cache, you can use the following command: flush contentGroup loginstaticobjects For browser cache clearance, there are multiple methods available. One approach I use on Chrome and Edge is to open the developer tools, right-click on the reload icon, and select "Empty cache and hard reset." No need to worry about this; I've already selected a couple of existing elements, and I'll share them here. TEXT1 Let's proceed with the first customization and add TEXT1 to the page as followed: Again, modify the script.js file from the new RfWebUI theme created located at /var/netscaler/logon/themes/NAME_OF_YOUR_NEW_RfWebUI_THEME/: const HTML2 = '<span style="color: lightgrey; margin: 0 auto; font-size: 12px; text-align: center; position: absolute; top: 50%">TEXT2</span>'; const HTML3 = '<span style="color: lightgrey; margin: 0 auto; font-size: 12px; text-align: center; position: absolute; top: 50%">TEXT3</span>'; elements = document.getElementsByClassName('logon-spacer'); elements[0].insertAdjacentHTML('afterbegin',HTML2); elements[1].insertAdjacentHTML('afterbegin',HTML3); In this example, we find the anchor element based on class name logon-spacer, when we use class name, JavaScript will return an array, this is the reason we use [0] and [1] to indicate the first spaces located in the left of the authentication form and the second spaces located on the right of it. The HTML code added here is a <span> to be inside of the existing element. TEXT4 and TEXT5 Now, let's add TEXT4 and TEXT5. Modify the script.js file from the new RfWebUI theme created located at /var/netscaler/logon/themes/NAME_OF_YOUR_NEW_RfWebUI_THEME/: const HTML6 = '<div style="color: lightgrey; margin: 0 auto; font-size: 12px; text-align: center"><BR><BR>TEXT6<BR><BR> </div>'; const HTML7 = '<div style="color: lightgrey; margin: 0 auto; font-size: 12px; text-align: center"><BR><BR>TEXT7<BR><BR> </div>'; element = document.getElementById("pluginExplicitAuthTop").parentNode; element.insertAdjacentHTML('beforebegin',HTML6); element.insertAdjacentHTML('afterend',HTML7); Here we select the parent element of the element with id pluginExplicitAuthTop and we create a <div> for TEXT6 before and another <div> for TEXT7 after. TEXT8 Now, let's add TEXT8: Modify the script.js file from the new RfWebUI theme created located at /var/netscaler/logon/themes/NAME_OF_YOUR_NEW_RfWebUI_THEME/: const HTML9 = '<div class="field CredentialTypenone"><div><span style="display: block; color: lightgrey; margin: 0 auto; font-size: 12px; text-align: center">TEXT9</span></div></div>'; const HTML10 = '<div class="field CredentialTypenone"><div><span style="display: block; color: lightgrey; margin: 0 auto; font-size: 12px; text-align: right">TEXT10</span></div></div>'; checkForm(); function checkForm () { if ( document.forms[0] ) { //Check if form exists div = document.getElementById("passwd").parentNode.parentNode; div.insertAdjacentHTML('beforebegin',HTML9); div.insertAdjacentHTML('afterend',HTML10); } else { setTimeout(checkForm, 50); //wait 50 ms, then try again } } If you need to insert HTML code within the authentication form, a slightly different approach is required due to its dynamic creation. In this scenario, we will first check if the authentication form already exists before injecting the new HTML code. If it doesn't exist, we will wait for 50 milliseconds before checking again. Conclusion In these instances, I applied a few styles to position the text as needed. However, it's essential to keep in mind that you have the option to utilize CSS for a cleaner separation of JS code and styling. To achieve this, simply make the necessary adjustments in the style.css file within the newly created RfWebUI theme. Please exercise caution with the character ' because the HTML code is encapsulated within two single quotation marks. To use it correctly, insert a backslash () before the single quote character to escape it. Remember that the objective here is not to offer JavaScript programming best practices but rather to showcase its capabilities and provide initial guidance to assist you in customizing your portal in a manner that ensures the changes endure through reboots and upgrades. In conclusion, the power to enhance and tailor your Citrix Gateway login page lies in your hands. Armed with the knowledge of how to insert HTML code via JavaScript, you can seamlessly integrate links, provide additional information, or offer valuable guidance to your users during their authentication process. The ability to customize this crucial portal empowers you to create a more user-friendly and informative experience that aligns with your organization's specific needs. So, embrace this opportunity and embark on the journey to create a login page that truly reflects your vision and aids your users every step of the way. Your portal's potential is limited only by your imagination, so go ahead and make it your own.
×
×
  • Create New...