Skip to content

Instantly share code, notes, and snippets.

@omniscient
Created June 7, 2016 18:11
Show Gist options
  • Save omniscient/b99a38f6d8f7f39a739e4ccf99c7b9b0 to your computer and use it in GitHub Desktop.
Save omniscient/b99a38f6d8f7f39a739e4ccf99c7b9b0 to your computer and use it in GitHub Desktop.
C# Citrix StoreFront WebAPI sample (Authentication, Application List, ICA File)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Newtonsoft.Json.Linq;
using RestSharp;
namespace ConsoleApplication3
{
public class ApplicationInfo
{
public string ID { get; set; }
public string AppTitle { get; set; }
public string AppLaunchURL { get; set; }
public string AppIcon { get; set; }
public string AppDesc { get; set; }
}
public class AuthCredential
{
public string AuthToken { get; set; }
public string SessionID { get; set; }
public string CSRFToken { get; set; }
}
public class Proxy
{
public static AuthCredential Authenticate(string storeFrontUrl, string username, string password, string domain)
{
var isSsl = storeFrontUrl.ToLower().IndexOf("https:", StringComparison.Ordinal) != -1;
var csrfToken = Guid.NewGuid().ToString();
var aspnetSessionId = Guid.NewGuid().ToString();
var request = new RestRequest("/PostCredentialsAuth/Login", Method.POST);
request.AddHeader("X-Citrix-IsUsingHTTPS", isSsl ? "Yes" : "No");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Csrf-Token", csrfToken);
request.AddCookie("csrtoken", csrfToken);
request.AddCookie("asp.net_sessionid", aspnetSessionId);
var authenticationBody = string.Format("username={0}\\{1}&password={2}", domain, username, password);
request.AddParameter("application/x-www-form-urlencoded", authenticationBody, ParameterType.RequestBody);
var client = new RestClient(storeFrontUrl);
//set the cookie container
client.CookieContainer = new System.Net.CookieContainer();
var response = client.Execute(request);
if (response.ResponseStatus == ResponseStatus.Error)
{
throw new Exception(string.Format("Error: {0}", response.ErrorMessage));
}
//parse cookie values
var returnedContent = response.Content;
var doc = new XmlDocument();
doc.LoadXml(returnedContent);
var statusNodeList = doc.GetElementsByTagName("Result");
if (statusNodeList.Count != 1) return null;
if (statusNodeList[0].InnerText.ToLower() != "success") return null;
//Restsharp is not returning the headers correctly. So let's parse them manually through the header property
var returnedValues = new Dictionary<string, string>();
foreach (var header in response.Headers.Where(i => i.Name == "Set-Cookie"))
{
var cookieValues = header.Value.ToString().Split(',');
foreach (string cookieValue in cookieValues)
{
var cookieElements = cookieValue.Split(';');
var keyValueElements = cookieElements[0].Split('=');
returnedValues.Add(keyValueElements[0], keyValueElements[1]);
}
}
var credentials = new AuthCredential
{
AuthToken = returnedValues["CtxsAuthId"],
CSRFToken = returnedValues["CsrfToken"],
SessionID = returnedValues["ASP.NET_SessionId"]
};
return credentials;
}
public static List<ApplicationInfo> GetResources(string storeFrontUrl, AuthCredential credentials)
{
var isSsl = storeFrontUrl.ToLower().IndexOf("https:", StringComparison.Ordinal) != -1;
var request = new RestRequest(@"Resources/List", Method.POST);
request.AddHeader("X-Citrix-IsUsingHTTPS", isSsl ? "Yes" : "No");
request.AddHeader("Accept", "application/json");
request.AddHeader("Csrf-Token", credentials.CSRFToken);
request.AddCookie("csrftoken", credentials.CSRFToken);
request.AddCookie("asp.net_sessionid", credentials.SessionID);
request.AddCookie("CtxsAuthId", credentials.AuthToken);
var client = new RestClient(storeFrontUrl);
var resourceList = client.Execute(request);
var json = resourceList.Content;
var jsonObject = JObject.Parse(json);
var resources = (JArray)jsonObject["resources"];
var applicationList = new List<ApplicationInfo>();
foreach (var resource in resources)
{
var appInfo = new ApplicationInfo();
appInfo.AppTitle = resource["name"].ToString();
try
{
appInfo.AppDesc = resource["description"].ToString();
}
catch (Exception)
{
appInfo.AppDesc = "";
}
appInfo.AppIcon = resource["iconurl"].ToString();
appInfo.AppLaunchURL = resource["launchurl"].ToString();
appInfo.ID = resource["id"].ToString();
applicationList.Add(appInfo);
}
return applicationList;
}
public static string GetIca(string storeFrontUrl, AuthCredential credentials, ApplicationInfo appInfo)
{
var isSsl = storeFrontUrl.ToLower().IndexOf("https:", StringComparison.Ordinal) != -1;
var request = new RestRequest(Method.GET);
request.AddHeader("X-Citrix-IsUsingHTTPS", isSsl ? "Yes" : "No");
request.AddHeader("Accept", "application/octet-stream");
request.AddHeader("Csrf-Token", credentials.CSRFToken);
request.AddCookie("csrftoken", credentials.CSRFToken);
request.AddCookie("asp.net_sessionid", credentials.SessionID);
request.AddCookie("CtxsAuthId", credentials.AuthToken);
var applicationUrl = string.Format("{0}/{1}", storeFrontUrl, appInfo.AppLaunchURL);
var client = new RestClient(applicationUrl);
var icaResponse = client.Execute(request);
var icaFile = icaResponse.Content;
return icaFile;
}
}
class Program
{
static void Main(string[] args)
{
var storeFrontUrl = @"http://YourStoreFrontServerURL/Citrix/StoreWeb";
var username = "YourUserName";
var password = "YourPassword";
var domain = "YourDomain";
// Logs in to Citrix store front
var credentials = Proxy.Authenticate(storeFrontUrl, username, password, domain);
// Gets the list of resources for the user
var _applications = Proxy.GetResources(storeFrontUrl, credentials);
// Pick the first application in the list
var app = _applications.First();
// Generate the ICA File
var _ica = Proxy.GetIca(storeFrontUrl, credentials, app);
// Save the ICA file to disk
var path = @"D:\temp";
string _icaFile = string.Format(@"{0}/{1}.ica", path, app.AppTitle);
if (File.Exists(_icaFile))
{
File.Delete(_icaFile);
}
File.WriteAllText(_icaFile, _ica, Encoding.UTF8);
}
}
}
@emakio
Copy link

emakio commented May 18, 2017

Hi,

the application give me an error on line "doc.LoadXml(returnedContent);"

ERROR "Additional information: "noindex" is unexpected token. The token expected """ or "'". Line 8, position15."

We have 2 version of StoreFront 2.6 and 3.9, both give me this error.

@harufu
Copy link

harufu commented Oct 26, 2017

Exact flow I needed to recreate it in Java. Great work!

@esward
Copy link

esward commented Aug 28, 2019

Thanks a lot Francois. It worked well for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment