Portal example

The following example uses the APIs to build your own portal where users can sign in, view a list of applications, and launch an application.

This examples requires you enable the authentication method “HTTP Basic”.

Save the following code in a file called ApiExample.html in your storefront directory, i.e. C:\inetpub\wwwroot\Citrix\[store name]. It uses JQuery which is already installed on the StoreFront server.

<!DOCTYPE html>
<html>
<head>
    <title>Web Proxy Api Example</title>
</head>
<style type="text/css">
    body {
        font-family: Segoe UI, Helvetica;
        font-size: 12px;
    }

    .resource {
        width: 75px;
        height: 75px;
        -ms-border-radius: 8px;
        border-radius: 8px;
        display: inline-block;
        padding: 5px;
        overflow: hidden;
        border: 1px solid firebrick;
        margin: 10px;
        position: relative;
        vertical-align: top;
    }

    .resource img {
            height: 42px;
            width: 42px;
            position: absolute;
            top: 6px;
            left: 21px;
        }

        .resource p {
            margin: 47px 0 0;
            text-align: center;
        }

        .resource:hover {
            background: lightgoldenrodyellow;
            cursor: pointer;
        }

    form, #friendlyname, #log-off, #logged-off {
        display: none;
    }

    form {
        width: 275px;
    }

    input[type=text], input[type=password] {
        width: 155px;
    }
    
    input[type=submit] {
        margin: 12px 0;
    }

    label {
        display: inline-block;
        width: 73px;
    }

    #hidden-iframes {
        /* The HDX plug-in ignores the launch if the ICA file is loaded into an element hidden with display: none so instead set visibility to hidden with size 0. */
        visibility: hidden;
        position: absolute;
        left: -999px;
        top: -999px;
        width: 0;
        height: 0;
    }
</style>
<script src="scripts/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

    var $configXml, resourcesData, url;

    $(document).ready(function () {
        // Web Proxy request to fetch the configuration
        ajaxWrapper({ url: 'Home/Configuration', dataType: 'xml', success: configSuccess });

        $('form').submit(function () {
            var username = $('#username').val(),
                password = $('#password').val();

            clearMessage();

            if (!username || !password) {
                showMessage('Enter a username and a password');
                return false;
            }

            // Web Proxy request to log the user on
            ajaxWrapper({
                url: 'PostCredentialsAuth/Login',
                dataType: 'xml',
                success: loginSuccess,
                error: loginError,
                data: { username: username, password: password }
            });

            return false;
        });

        $('#log-off').click(function () {
            // Web Proxy request to log the user off
            url = ($configXml.find('authManager').attr('logoffURL'));
            ajaxWrapper({ url: url, dataType: 'text', success: logoffSuccess });
            return false;
        });
    });

    function configSuccess(data) {
        $configXml = $(data);
        // The userLanguages setting reflects the browser's Accept-Language header, which can be used to localize the client UI
        // var languages = $configXml.find('session').attr('userLanguages');

        // Web Proxy request to enumerate the available authentication methods
        ajaxWrapper({ url: 'Authentication/GetAuthMethods', dataType: 'xml', success: getAuthMethodsSuccess });
    };

    function getAuthMethodsSuccess(xmlData) {
        var url;

        $(xmlData).find('method').each(function (index, elt) {
            var name = $(elt).attr("name"),
                authUrl = $(elt).attr("url");

            if (name == 'PostCredentials') {
                url = authUrl;
                return false; // Break out of the 'each' loop
            } else {
                return true; // Continue iterating
            }
        });

        if (url) {
            showLogonForm();
        } else {
            showMessage('PostCredentials authentication is not available - check HttpBasic is enabled at the Authentication service');
        }
    }

    function loginSuccess(data) {
        var $loginXml = $(data),
            result = $loginXml.find('Result').text();

        if (result == 'success') {
            $('form').hide();
            $('#log-off').show();

            // Web Proxy request to enumerate the resources available to the user
            url = $configXml.find('resourcesProxy').attr('listURL');
            ajaxWrapper({ url: url, success: listResourcesSuccess });
        } else {
            showMessage('Login failed - try again');
        }
    }

    function loginError() { console.log('Login failed'); }

    function logoffSuccess() {
        showMessage('You have logged off successfully');
        showLogonForm();
    }

    function showLogonForm() {
        $('#log-off').hide();
        $('#resources-container').empty();
        $('form').show();
        $('#username').select().focus();
    }

    function listResourcesSuccess(data) {
        var markup = '';

        resourcesData = data.resources;

        for (var i = 0; i < resourcesData.length; i++) {
            markup += generateResourceMarkup(resourcesData[i], i);
        }

        $('#resources-container').append($(markup))
                                 .off('click')
                                 .on('click', '.resource', null, prepareLaunch);

        // Web Proxy request to fetch the user's full name
        url = ($configXml.find('authManager').attr('getUsernameURL'));
        ajaxWrapper({ url: url, dataType: 'text', success: getUsernameSuccess });
    }

    function getUsernameSuccess(data) {
        showMessage('Welcome ' + encodeHtml(data));
    }

    function prepareLaunch() {
        var index = $(this).attr('id'),
            resource = resourcesData[index];

        console.log('launch: ' + resource.name);

        if ($.inArray('ica30', resource.clienttypes) == -1) {
            console.log('Resource does not support ICA launch');
            return;
        }

        // Web Proxy request to check whether the resource is ready to launch
        ajaxWrapper({ url: resource.launchstatusurl, success: launchStatusSuccess, error: launchStatusError });

        function launchStatusSuccess(data, textStatus, xhr) {
            if (xhr.getResponseHeader('CitrixWebReceiver-Authenticate')) {
                // If the Web Proxy session has terminated for any reason, this authentication challenge header is returned.
                // After authentication, all calls to the Web Proxy should be prepared to deal with this challenge, typically
                // by prompting the user to log on again.
                console.log('No session - user must log in again');
                return;
            }

            console.log('launch status: ' + data.status);
            // Note, data.status is set to 'retry' if a desktop VM needs to be started up by the server.
            if (data.status == 'success') {
                performLaunch(resource);
            }
        }

        function launchStatusError() { console.log('Get launch status failed'); }
    }

    function performLaunch(resource) {
        var icaFileUrl = resource.launchurl,
            csrfToken = getCookie('CsrfToken'),
            currentTime = (new Date()).getTime(),
            frameId = "launchframe_" + currentTime;

        // To initiate a launch, an ICA file is loaded into a hidden iframe.
        // The ICA file is returned with content type "application/x-ica", allowing it to be intercepted by the Citrix HDX
        // browser plug-in in Firefox/Chrome/Safari. For IE, the user may be prompted to open the ICA file.
        $('#hidden-iframes').append('<iframe id="' + frameId + '" name="' + frameId + '"></iframe>');

        if (csrfToken != null) {
            icaFileUrl = updateQueryString(icaFileUrl, "CsrfToken", csrfToken);
        }

        // Web Proxy request to load the ICA file into an iframe
        // The request is made by adding
        icaFileUrl = updateQueryString(icaFileUrl, 'launchId', currentTime);
        $("#" + frameId).attr('src', icaFileUrl);

        console.log('perform launch - url: ' + icaFileUrl);
    }

    function generateResourceMarkup(resource, index) {
        var result = '<div id="' + index + '" class="resource">';

        result += '<img class="resource-icon" alt="' + encodeHtmlForAttr(resource.name) + '" src="' + resource.iconurl + '">';
        result += '<p class="resource-name">' + encodeHtml(resource.name) + '</p>';
        result += '</div>';

        return result;
    }

    function showMessage(message) { $('#message').text(message); }

    function clearMessage() { showMessage(''); }

    function getCookie(name) {
        var results = document.cookie.match('(^|;) ?' + name + '=([^;]*)');
        return results ? unescape(results[2]) : null;
    }

    function updateQueryString(url, key, value) {
        var re = new RegExp("([?|&])" + key + "=.*?(&|$)", "i");
        if (url.match(re)) {
            return url.replace(re, '$1' + key + "=" + value + '$2');
        } else {
            return url + (url.match(/\?/) ? '&' : '?') + key + "=" + value;
        }
    }

    function encodeHtml(value) {
        return $('<div/>').text(value).html();
    }

    // Additionally encode double quotes to allow values to be used within double-quoted HTML attributes
    function encodeHtmlForAttr(value) {
        return encodeHtml(value).replace(/"/g, '&quot;');
    }

    function ajaxWrapper(options) {
        var defaultOptions = {
            type: 'POST',
            dataType: 'json',
            traditional: true,
            beforeSend: function (jqXHR) {
                var csrfToken = getCookie('CsrfToken');
                if (csrfToken != null) {
                    jqXHR.setRequestHeader("Csrf-Token", csrfToken);
                }
                var isUsingHttps = location.protocol.toLowerCase() == "https:" ? "Yes" : "No";
                jqXHR.setRequestHeader("X-Citrix-IsUsingHTTPS", isUsingHttps);
            },
            error: function () {
                console.log('Ajax error accessing URL: ' + options.url);
            }
        };

        options = $.extend({}, defaultOptions, options);
        $.ajax(options);
    }
</script>
<body>
    <h1>Web Proxy API Example</h1>
    <form>
        <fieldset>
            <legend>Enter credentials</legend>
            <p>
                <label for="username">User name:</label>
                <input type="text" id="username" name="username" />
            </p>
            <p>
                <label for="password">Password:</label>
                <input type="password" id="password" name="password" />
            </p>
        </fieldset>
        <input type="submit" id="login-button" name="login-button" value="Log On" />
    </form>
    <a id="log-off" href="#">Log Off</a>
    <p id="message"></p>
    <div id="resources-container"></div>
    <div id="hidden-iframes"></div>
</body>
</html>
<!--NeedCopy-->
Resources
StoreFront Web API OpenAPI Specification
Copy Download
Portal example

In this article