Unable to get LLCookie using ll.login function

Hi all, we recently migrated our OpenText to new environment (Azure tenant actually). And an old proven method of getting LLCookie stopped working. Nothing is being returned when we Post. This is the code (C#), I am trying to execute, and CookieContainer is empty :-(. Any help would be very much appreciated.

        var url = "https://<baseurl>/otcs/cs.exe";
var cookieContainer = new CookieContainer();
var loginUri = new Uri(url);

using (var httpClientHandler = new HttpClientHandler
{
CookieContainer = cookieContainer,
AllowAutoRedirect = true,
UseCookies = true,
})
{
using (var httpClient = new HttpClient(httpClientHandler))
{
// Create a login form
var body = new Dictionary<string, string>()
{
{ "func", "ll.login" },
{ "username", privateLinkUserName },
{ "password", privateLinkPassword },
};
var content = new FormUrlEncodedContent(body);

var request = new HttpRequestMessage(HttpMethod.Post, loginUri)
{
Content = content,
};

var response = httpClient.SendAsync(request).Result;

var cookies = cookieContainer.GetCookies(loginUri).Cast<Cookie>().ToList();
var cookie = cookies.FirstOrDefault(x => x.Name == "LLCookie");
}
}

Comments

  • appuq
    appuq Member

    There is a function on the admin page which is something like get login

    I am not sure because you said it used to work in POST but the command I show is a GET

    The simplest flow is

    1. The user wants to get into CS and is not authenticated
    2. The user is forwarded to OTDS
    3. OTDS does the handshake and allows the user to Resource(CS)
    4. LLcookie a memory cookie is on the browser
    5. The user does what needs to be done.

    OT is ever trying to secure breaches etc so mostly in code they recommend using

    1. if you were using REST API you could get an authentication token from OTDS(my favorite) or the CS itself (which can lead to multiple servers not liking it). With OTDS you are more than assured of getting in. I wrote a SOAP API integration in our product which gets an authentication token first and then I use that token to end the actual SOAP API code.

    Tweaking the flags I showed above based on security parameters could most likely be at a risk you are assuming as OT probably never gives a clear answer on how they are getting used. However, chances are those flags were built so some customers could still use in secure or legacy coding.

  • Thank you, this is confirming some of my thoughts, however:

    • This is an API we are working on, so the user is not involved.
    • I did make it work with SOAP API authentication too, but was hoping to only use HTTPs calls, thus posting this question here.
    • We used to call POST to login, so you are right, GET is probably less desirable.

    So, to continue on this point, is there a way to get OTDS cookie, using the HTTP method? Code sample maybe?

    Thank you!

  • appuq
    appuq Member
    edited July 29 #4

    I use this REST API call in POSTMAn to get the OTDSSSO* ticket. Any valid RESTAPI call to CS CS will accept OTCSTICKET or OTDSTICKET, mind you these are not cookie-based.REST api explicitly looks for a header not cookie in the call.

    Why I mentioned SOAP is because I wrote a SOAP API CreateAndUpdate workspaces call in Maximo but the Soap call expects an authentication token. The SOAP API auth or rest api auth can easily be interchanged. I used REST because it was easier.

    This is how people usually get to the OTDSTicket. Even if you don't have Postman OT supplies a swagger page accessible at http:otdserver: port/otdsws/api/index.html, it has a curl interface with which you can test most of the otds API.

    The smartui which is browser-based invokes an iframe to OTDS and once it gets the ticket, it uses it for further CS things.One never sees the vanishing iframe.

  • Thank you, just tried http://<baseurl>:8080/otdsws/rest/authentication/credentials, and seeing Error: connect ECONNREFUSED.

    Also, must this be done over http or should https be used?

  • appuq
    appuq Member
    edited July 29 #6

    http or https does not make a difference.

    OTDS server will be in the configuration for your content server. Since I am kind of the developer/admin of CS I assumed you would know where your OTDS server is and whether it is http or https.In any case one can know the directory server by going to this link as an CS admin

    http://<my otdsserver on http>:<port>/otcs/cs.exe?func=otdsintegration.settings

    some postman screencaps

    My swagger page

    PS When you go to Swagger try executing GET /authentication/headers this will get the ticket of the user who identifies to OTDS assuming an SSO handler has been configured. This is what teh SmartUI uses when a user hits CS and retrieves the token.

    When using OTDS your content type is JSON when it comes to CS it is all over the place…as OTDS is a modern lightweight application written exclusively for rest.

  • Thank you, I see a ticket, while executing https://<ourbaseotdsurl>:8443/otdsws/rest/authentication/credentials in Postman!!!

    "ticket": "*OTDSSSO*Abx….AAA**",

    Hopefully last question - should the whole "ticket" be used as LLCookie, or is there some other way, like adding it to Authorization header?

  • appuq
    appuq Member

    When you actually call a rest api like suppose I want to create a Folder this is how we use it.

    In parameters we actually go to developer.opentext.com an look at SAAS stuff and find REST API(buried deep and deep)

    Then where you see the headers we put that long ticket like

    Note as mentioned above OTCS does not always accept JSON as it is an old CGI based application so mostly complicated calls are always a fake body inside body and the payload going.In teh notes OT has that as Implementation Notes XHR code produced by postman

    Note otcsticket is a ticket that CS issues will be valid only for that server mostly otdsticket is loadbalancer safe.

    // WARNING: For POST requests, body is set to null by browsers.
    var data = new FormData();

    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;

    xhr.addEventListener("readystatechange", function() {
    if(this.readyState === 4) {
    console.log(this.responseText);
    }
    });

    xhr.open("POST", "http://content server/otcs/cs.exe/api/v1/nodes?type=0&parent_id=377091&name=appu");
    xhr.setRequestHeader("otdsticket", "*OTDSSSO*AZ the long long long long ticket*");
    xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gZ");

    xhr.send(data);

  • Thanks again, this is basically what I was just able to successfully implement in Postman (moving to C# next). I have added "OTDSTicket" obtained above, as a header (not a Cookie!), and I seem to be able to execute regular function calls. Looking good so far!

    appuq, thanks for all the help!

  • appuq
    appuq Member

    you are most welcome,hope you get successful in your C#,

    I have written code in C# and Java doing file uploads and downloads in CS and that is another aspect modern programmers stumble on as CS will only accept Files from a place as a Filesystem object as a regular POST of a web form. Especially when using the Postman interface and adding a file Postman does all the magic so that a post using a multipart-formdata is constructed on the fly.

    A lot of high-level packages exist for Java, python, and C# so that you do not have to bend over backward when doing those however in my case I had a project where I was working with IBM Tibco and it had very old Java at the Tibco server so I used java POJO to completely upload a file . Fiddler and Postman and general reading on the web helped me do that.

  • Exactly. I actually have uploads working just fine using OTCSTicket and REST API (multipart formdata of course). And it's fairly well documented, with Postman available. This was needed for some legacy function execution which doesn't seem to accept OTCSTicket unfortunately. Now this seems to also be on the way to be working. Thanks again,