How to Save Web Interface Usernames in a Cookie

In the article titled “How to Enable AutoComplete for Web Interface Logon”, I explained how to enable the AutoComplete functionality of web browsers in order to save usernames and/or passwords for Citrix Web Interface. As the article explained, there are a lot of moving parts to the solution such as web browser settings, Protected Storage, JavaScript workarounds, etc. In this article, I will explain how to accomplish something similar by using cookies to remember the last username entered for Web Interface.

In the article titled “How to Enable AutoComplete for Web Interface Logon”, I explained how to enable the AutoComplete functionality of web browsers in order to save usernames and/or passwords for Citrix Web Interface. As the article explained, there are a lot of moving parts to the solution such as web browser settings, Protected Storage, JavaScript workarounds, etc. In this article, I will explain how to accomplish something similar by using cookies to remember the last username entered for Web Interface.

How it Works (if you do not really care how it works, you can just download the modification at the end of this post)

There are really only two parts to this solution. Part 1 – store the username in a cookie. Part 2 – get the username from the cookie and populate the “user name” field at logon. There is a little Web Interface SDK work to obtain the username, but I will explain what is going on.

 

Part 1 – Storing the Username in a Cookie

There are two steps to accomplish this part.

First, we need to get the username after it is validated by Web Interface. An ideal place to get the authenticated username is applistView.ascx. applistView.ascx is the user control in Web Interface that is responsible for displaying a list of applications a user has access to. So, we know if we got to applistView.ascx in the Web Interface logon/application enumeration process that a username should be available.

Second, we need to store the username in a cookie (this is pretty easy in comparison to getting the username).

Here is the code:

Modify applistView.ascx

Find the following text (around line 10):

<!–#include file=”../serverscripts/include.aspxf”–>

Paste the following right after this line

<%

//----------------------------------------------------------------
// WI mod
//----------------------------------------------------------------

string username = String.Empty;

// Get username
com.citrix.authentication.tokens.AccessToken accessToken = com.citrix.wi.pageutils.Authentication.authGetPrimaryAccessToken(wiContext.getWebAbstraction());
if(accessToken != null)
{
if(accessToken is com.citrix.authentication.tokens.GuestToken)
{
// Guest
username = wiContext.getString("Guest");
}
else
{
username = accessToken.getUserIdentity();
}
}

HttpCookie userCookie = Request.Cookies.Get("WI_username");

if(userCookie == null)
{
// Cookie doesn't exist, so create it
userCookie = new HttpCookie("WI_username");
}
else if(userCookie.Value != username)
{
// Need to update the cookie value
Response.Cookies.Set(Request.Cookies.Get("WI_username"));
}

userCookie.Value = username;
userCookie.Expires = DateTime.Now.AddDays(100);
Response.Cookies.Add(userCookie);	

//----------------------------------------------------------------
// End WI mod
//----------------------------------------------------------------

%>

Code explanation:

First, we need to get an AccessToken (see line 10 above). In the Web Interface object model, an AccessToken “…encapsulates information that may be used for authorization and authentication when a Subject requires access to a resource.” What that means in layman’s terms is an AcessToken basically holds your username, password, domain, identity, etc. (you can actually use the PasswordBasedToken Interface to get the password of a user if you wanted to as described in this article).

After we get the AccessToken, we can test to see if this is an anonymous user or not (an anonymous user would have a GuestToken) on lines 12-23 above. If the token is not a GuestToken, then we know we have an authenticated user. There are currently 3 methods you can use to get the user details from the AccessToken:

  1. getAccountIdentity() – gets an AccountIdentiy object.
  2. getShortUserName() – returns the username as a string. Example – if your user identity was domain\jasonco, getShortUserName() returns “jasonco”.
  3. getUserIdentity() – returns the entire logon identity as a string. Example: domain\username or [email protected] (if using UPN). I chose getUserIdentity() in the code above.

The rest of the code is pretty straight forward – it just creates or updates the cookie named WI_username. You could actually name this cookie anything you wanted.

Part 2 – Retrieving/Populating the Username from the Cookie

This part is quite a bit easier than the first part. All we need to do is to get the cookie, if any, from the previous code and populate the username field on the log on screen. The logon screen code can be found in loginMainForm.inc.

Here is the code:

Modify loginMainForm.inc

Find the following text (around line 106):

<td colspan="2">
    <input type='text' name='<%=Constants.ID_USER%>' id='<%=Constants.ID_USER%>'
        class='loginEntries<%=viewControl.getExplicitDisabled()?" loginEntriesDisabled":""%>'
        maxlength='<%=Constants.LOGIN_ENTRY_MAX_LENGTH%>' <%=viewControl.getExplicitDisabledStr()%>
        tabindex='<%=Constants.TAB_INDEX_FORM%>'

Paste the following right after this text:

<%
//----------------------------------------------------------------
//       WI mod
//---------------------------------------------------------------- 

HttpCookie userCookie = Request.Cookies.Get("WI_username"); 

if(userCookie != null)
{
%>
    value='<%=userCookie.Value %>'
<% 

} 

//----------------------------------------------------------------
//       End WI mod
//----------------------------------------------------------------
%>

Code explanation:

The <input… tag above is the field where you fill in your username in loginMainForm.inc. The code inserted above sets the value of the input tag to whatever was stored in the WI_username cookie (if there was anything stored in the cookie at all).

If you want to implement this in your environment and do not feel like copying and pasting all this code, you can download the modified files below:

download Modification for Web Interface 5.1

How to Enable AutoComplete for Web Interface Logon

The logon page for Citrix Web Interface explicitly disables the web browser functionality of saving form data. But, what if you want to let your users save their username (especially if they have a particularly long UPN)? This article will show you how to re-enable this functionality for both Web Interface 4.x and 5.x.

The logon page for Citrix Web Interface explicitly disables the web browser functionality of saving form data. But, what if you want to let your users save their username (especially if they have a particularly long UPN)? This article will show you how to enable AutoComplete functionality for both Web Interface 4.x and 5.x.

Disclaimer – I would highly recommend only implementing this solution in a secure internal environment. You do not want your usernames or passwords floating around out there in the public.

 

Citrix Web Interface AutoComplete

 

 

How Web Interface disables AutoComplete
Web Interface hasn’t always disabled the AutoComplete functionality of web browsers.  I actually think it is wise Citrix did start disabling AutoComplete by default because a lot of Web Interface sites are external-facing and AutoComplete can be a bad thing in an external scenario. The way Web Interface disables AutoComplete is by adding a property to the <form> tag in the HTML.  Simply adding autocomplete=”off” will disable AutoComplete for all <input> elements within the <form>. If you look at the rendered WI login page’s HTML, you will see <form… autocomplete=”off”>.

Enabling AutoComplete for Web Interface 4.x
Enabling AutoComplete for Web Interface 4.x is actually quite simple.  All you really need to do is get rid of the autocomplete=”off” property in the <form> tag.  To do this:

Modify loginView.ascx

Change this:  <form method="POST" action="<%=PAGE_LOGIN%>" name="NFuseForm" autocomplete=”off”>

To this:  <form method="POST" action="<%=PAGE_LOGIN%>" name="NFuseForm">

A possible downside to this is that passwords will be saved as well.  If you do not want passwords to be saved, you can tell just the password field to disable AutoComplete.  To do this:

Modify loginMainForm.inc

Change this: <input type='password'…

To this: <input autocomplete="off" type='password'…

Enabling AutoComplete for Web Interface 5.x
Enabling AutoComplete for web Interface 5.x is the same as enabling AutoComplete in Web Interface 4.x with one exception.  Web Interface 5.x does not use a <input type=”submit” /> button to submit form data.  Instead, Web Interface 5.x uses JavaScript to submit the form data.  This causes an issue with AutoComplete because AutoComplete only commits data to Protected Storage via a <input type=”submit” /> button.  So, to get around this bug “feature”, we need to do some trickery.

Since AutoComplete only works with <input type=”submit” /> buttons, we need to add one of these buttons to our login page.  We do not actually want to see this button since it is just there to facilitate the AutoComplete functionality, so we set the display style on the submit button to none (<input type=”submit” style=”display: none” />)

Finally, we need to manipulate the Web Interface JavaScript code that submits to form to tell it to “virtually press” our hidden submit button (this will cause AutoComplete to save the data).  Here are all the steps necessary to implement AutoComplete in Web Interface 5.x:

Step 1 – Modify layout.ascx

Change this:  <form method="post" action="<%=FormAction%>" name="<%=Constants.ID_CITRIX_FORM%>" autocomplete="off">

To this: <form method="post" action="<%=FormAction%>" name="<%=Constants.ID_CITRIX_FORM%>">

 

Step 2 – Modify loginMainForm.inc

Add the following to the bottom (right after </table>):

<input type="submit" value="submit" id="hiddenSubmitButton" style="display:none" />

This is our hidden fake submit button that will trigger AutoComplete to save the data.

Step 3 – Modify login.js

Change this:

function submitForm() {
    if (!isSubmitted) {
        changeLoginBtnColor(false);

        isSubmitted = true;

        var loginBtn = document.getElementById("loginButtonWrapper");
        if(loginBtn){
            loginBtn.style.color = "#aaaaaa";
        }

        disableLinks();

        document.forms[0].submit();
    }
}

To this:

function submitForm() {
    if (!isSubmitted) {
        changeLoginBtnColor(false);

        isSubmitted = true;

        var loginBtn = document.getElementById("loginButtonWrapper");
        if(loginBtn){
            loginBtn.style.color = "#aaaaaa";
        }

        disableLinks();

        var hiddenSubmitBtn = document.getElementById("hiddenSubmitButton");
        if(hiddenSubmitBtn.click) {

                hiddenSubmitBtn.click();
        }
        else {
                document.forms[0].submit();
        }
        return false;
    }
}

The highlighted code basically tells the JavaScript submit function to “virtually click” the hidden submit button we added to loginMainForm.inc.
Again, if you want to disable passwords from being saved, add autocomplete=”off” to all the <input type=’password’ … /> fields in loginMainForm.inc.

 

 

Other factors of using AutoComplete
In order for AutoComplete to save form data, the feature needs to be turned on in your web browser.  For Internet Explorer, this can be found by going to Tools -> Internet Options -> Content tab.

Internet Explorer AutoComplete

For Firefox, this can be found by going to Tools -> Options -> Privacy.

FF-AutoComplete

AutoComplete stores form data in Protected Storage – which means that the Protected Storage service needs to be running.   Protected Storage can, on occasion, get corrupted.  See this Microsoft support article about this situation: http://support.microsoft.com/kb/306895

Silverlight Web Interface Sneak Peak

What do you get when you combine Citrix Web Interface, Microsoft Silverlight, and AJAX? You get my latest Web Interface modification. Read on to find out more…

I have been preparing for some Citrix Synergy and BriForum sessions where I will be presenting on Web Interface internals and customizations. One of the customizations I put together is an adaptation of Narenda Wicaksono’s Silverlight TSWeb Access for Windows Server 2008 Terminal Services. I created a similar application built around the Citrix Web Interface API. I am using Microsoft Silverlight 2.0, AJAX, Web Interface APIs, and Citrix XenApp 4.5. Check out this short video to see more:

I know it was hard to tell a lot of details from the video, but I will post more details soon.

Template updates for Citrix Web Interface 4.6

Two of my most popular posts (“Super Easy Customization of Citrix Web Interface 4.x” and the “Citrix Web Interface SharePoint Look and Feel Template” download) have been updated to include support for Citrix Web Interface 4.6.

In preparing for some Citrix Synergy and BriForum sessions, I made some updates to the following two articles:

The Super Easy Customization of Citrix Web Interface 4.x article has been updated to include a “bare bones” template for Web Interface 4.6.

The Citrix Web Interface SharePoint Look and Feel Template download has been updated to include a SharePoint look and feel template for Web Interface 4.6.

Feel free to use/modify these templates for your own use.

Super Easy Customization of Citrix Web Interface 4.x

UPDATED (now includes 4.2 template). There are several resources out there explaining how to customize or brand Citrix Web Interface. The easiest method I’ve found by far is to modify the layout.ascx user control. Using the technique outlined in this article, you can quickly give your Web Interface site a brand new look and feel.

There are several resources out there explaining how to customize, or brand, Citrix Web Interface. The easiest method I’ve found by far is to modify the layout.ascx user control. Using the technique outlined in this article, you can quickly give your Web Interface site a brand new look and feel.

The layout.ascx user control
The heart of the Web Interface layout is a file called layout.ascx. Layout.ascx is a user control that “constructs” the Web Interface authentication and applications page’s HTML. There are two different layout.ascx files for every Web Interface site. These layout.ascx files can be found at path_to_your_wi_site\auth\include (login page) and path_to_your_wi_site\site\include (applications page).

UPDATE: The layout.ascx files in Web Interface 4.6 are located at path_to_your_wi_site\app_data\auth\include (login page) and path_to_your_wi_site\app_data\site\include (applications page).

Cutting layout.ascx to the core
To get started, open up the layout.ascx file located at path_to_your_wi_site\site\include. Next, strip out all the markup and code between the opening and closing <body> tags except the <wi:Welcome runat=”server”/>, <wi:MessageCenter>, <wi:Toolbar>, and <asp:PlaceHolder> tags. These tags are the “meat and potatoes” of the Web Interface applications page. The <wi:Welcome runat=”server”/> tag displays the welcome message. The <wi:MessageCenter> tag displays the message center. The <wi:Toolbar> tag shows the toolbar holding the refresh, settings, and help buttons. The <asp:PlaceHolder> tag shows all the published applications for the authenticated user.

Note: it is not necessary to use any of these tags in your final markup although it would be pretty silly not to include at least the <asp:PlaceHolder> tag.

The end result should look something like this:

<body text="#000000" bgcolor="#FFFFFF" LINK="#000000" VLINK="#000000" ALINK="#000000" topmargin='0' leftmargin='0' marginheight="0" marginwidth="0" onLoad="onLoadLayout();" dir="<%=getString("TextDirection", currentLocale)%>">

<wi:Welcome runat="server"/>
<wi:MessageCenter runat="server"/>
<wi:Toolbar runat="server"/>
<asp:PlaceHolder id="ViewPlaceHolder" runat="server" />

</body>

This produces a “bare bones” Web Interface page.  Check it out:

Click to enlarge
Click to enlarge

If you would like a copy of this “bare bones” layout.ascx file, you can download it below:

layout_40.zip (for Web Interface 4.0)

layout_42.zip (for Web Interface 4.2)

layout_46.zip (for Web Interface 4.6)

Giving layout.ascx a facelift
Now, start adding your markup to the layout.ascx file and place the above mentioned tags where you want. If you want to modify text and color properties of the application links, the easiest place to do that would be the style.inc file located in the same place as the layout.ascx file. You can use this same technique for the layout.ascx file located at path_to_your_wi_site\auth\include to customize the login page.

Note: if you need to grab the username and password of the authenticated user, check out this article for instructions on how to do it.

Using the method described in this article, I made Citrix Web Interface look and feel like Microsoft SharePoint Portal Server 2003. Check it out below:

Citrix Web Interface with a Microsoft SharePoint look and feel
Click to enlarge

You may ask yourself, “Why would I ever want to do this?”.  Well, in this case the company was migrating from a custom written Intranet portal to Microsoft Office SharePoint Portal Server 2003 at the same time they were migrating from Citrix MetaFrame XP to Citrix Presentation Server 4.0.  The SharePoint migration would take place after the PS4 migration.  So, to minimize end-user impact, the custom portal was replaced with this SharePoint “fake-out”.  When the portal migration was ready, the front end never really looked that different to the end user, but the back end was vastly different.

If you would like a copy of the templates I used to make Web Interface look and feel like SharePoint, you can download them here

.

Citrix Web Interface “SharePoint Look and Feel” Template

Download a template that makes Citrix Web Interface look and feel like Microsoft Office SharePoint Portal Server 2003.

In the article titled Super Easy Customization of Citrix Web Interface 4.x I mentioned that I once customized Citrix Web Interface to look like Microsoft SharePoint Portal Server 2003 during a transition time. I have had some requests for the templates I used for that process. So, I have made these customizations available below:

 Citrix Web Interface 4.0 SharePoint Template

 Citrix Web Interface 4.2 SharePoint Template

 Citrix Web Interface 4.6 SharePoint Template

Screenshots:

Login Screen

Click to enlarge

Applications Page

Click to enlarge

Controlling Access to Web Interface using Web Interface Access Control Center

This article describes the features in the new Web Interface Access Control Center. Using the Web Interface Access Control Center you can limit access to Citrix Web Interface/Secure Gateway as well as view usage statistics.

Have you ever had a need to allow only a subset of your users access to Citrix Web Interface or Secure Gateway? This is especially useful if you use an internal Web Interface and an external Web Interface/Secure Gateway environment. You might want to let anybody log on through the internal Web Interface, but restrict access through the external Web Interface/Secure Gateway. Sam Jacobs created a utility to do just that at http://www.ipm.com/home/freecode/RestrictedUsers.zip. The basic concept of this modification is to place a list of users in a text file on your Web Interface server. Then, the code looks in this file at login time to see if the authenticating user is allowed to continue.

This concept works quite well, but I had a request to allow non-technical people to control the access list. Rather than give them rights to the server to modify the text file, I came up with a slightly different solution – the Web Interface Access Control Center. This solution involves placing the allowed users in a database table and comparing the authenticating user to the database table, rather than a text file, at login time. As an added bonus, this solution logs all access attempts to the database as well.

To help implement this solution, I created an ASP.NET interface to allow adding and removing users from the list. This utility integrates with Active Directory to display available users to add to or remove from the access list. In addition, the utility analyzes usage and presents this information in a drill-down format.

Download the Web Interface Access Control Center

The Components

The Web Interface Access Control Center consists of three logical components; a database to store allowed users and access activity, a Citrix Web Interface server, and an IIS Web Application server running the .NET Framework version 2.0 to host the end-user utilities. I say these are three logical components because all three components can reside on the same physical server.

The Database
The database can be any ODBC compliant database such as Microsoft SQL, MSDE, MySql, etc. The database has a very simple structure consisting of only two tables; the WI_Access table to store which users are permitted access via Web Interface, and WI_AccessLog to store access attempts.

The Web Interface Server
Naturally you will need a Citrix Web Interface server. You will need to make one modification in order for this solution to work. The modification instructions can be found in the setup instructions accompanying the download. One thing to note however is if there is a firewall between the Web Interface server and the database, port 1433 will need to opened in order for SQL communication to occur.

The IIS Web Application Server
The IIS Web Application server reads information from the database and reports this information in a drill down fashion. The virtual directory that the web application runs from will need to be configured to use the .NET Framework version 2.0 (this is covered in the setup instructions).

Component Communications

Web Interface Access Control Center Communications

Screen Shots

Access Control List

Click to enlarge

Usage Calendar

Click to enlarge

Day Detail

Click to enlarge

Hour Detail

Click to enlarge

User Detail

Click to enlarge

I hope you find this tool useful. But, keep in mind that while every effort has been made to test this tool, this tool is still in “beta” and may contain bugs. Also, the modification made to Web Interface is not supported by Citrix.

Web Interface Access Control Center

Have you ever had a need to allow only a subset of your users access to Citrix Web Interface or Secure Gateway? The Web Interface Access Control Center does that and a lot more.

version 1.0

The Web Interface Access Control Center controls access to Citrix Web Interface/Secure Gateway on a named user basis and logs access attempts.  The Web Interface Access Control Center also has a reporting module that delivers drill down statistics on your Citrix Web Interface/Secure Gateway usage.  Read more in the article titled Controlling Access to Web Interface using the Web Interface Access Control Center.

Web Interface Access Control Center

How to get the Username AND Password of a user in Citrix Web Interface 4.0

Have you ever wanted to get the username and password from an authenticated user in Citrix Web Interface? This article tells you exactly how to do just that.

Have you ever wanted to get the username and password from an authenticated user in Citrix Web Interface? I was once tasked to grab the username and password of the authenticated Citrix Web Interface user and pass those credentials along to a custom Lotus Notes web application. Using the Web Interface SDK (available at http://apps.citrix.com/cdn/sdk/webinterface_sdk.asp), I was able to get just what I needed. Here is how it’s done:

The down and dirty explanation
The first thing you’ll need to understand is the object model Citrix uses in Web Interface. Citrix provides you with a lot of base classes you can use to programmatically get the information you need. All these classes are documented in the SDK. The class we’re interested in for this example is the AccessToken class. The AccessToken class allows you to get the user’s username (but not the user’s password). To get the user’s password, you’ll need to use the PasswordBasedToken Interface. The AccessToken class implements the PasswordBasedToken interface which exposes a method called getPassword(). This method returns a string that is the user’s password. Check out the code below:

The code
<%
PasswordBasedToken pbt = null;
AccessToken ac = authGetPrimaryAccessToken();
pbt = (PasswordBasedToken)ac;

string strUsername = ac.getShortUserName();
string strPassword = pbt.getPassword();
%>

That was easy (almost too easy).
Notice the use of the authGetPrimaryAccessToken(). This is a function that Citrix gives you to get the primary access token holding the credentials the user used to authenticate to Web Interface. This function can be found at path_to_your_wi_server\site\serverscripts\authentication.cs and path_to_your_wi_server\auth\serverscripts\authentication.cs

The code placement
Ok, now you know the down and dirty explanation and the code used to get the username and password. So, where do you put this code? One place you could use is the layout.ascx file located at path_to_your_wi_server\site\include. Layout.ascx is a user control that constructs the look and feel of the Web interface page after authentication (see this article for more information). Just place the code before the tag. Now you can use the variables strUsername and strPassword wherever you like in the code.

Putting it all together
Here is the final product

Layout.ascx

<%

PasswordBasedToken pbt = null;
AccessToken ac = authGetPrimaryAccessToken();
pbt = (PasswordBasedToken)ac;
string strUsername = ac.getShortUserName();
string strPassword = pbt.getPassword();
%>

<html>
<head>
  <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
  <meta NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW, NOARCHIVE">
  <title><%=PageTitle%></title>
. . .

I hope this helps some of you out there trying to bring together disparate systems.