Challenges using CS ReST API to extend Content Server UI

Options

Hi,
This is less of a question and more a series of observations. When I was first exposed to the ReST API, I thought it might be a good option for designing UI components to be used within Content Server. The main problem is authenticating between them. That is, if you are logged into the CS UI, you are not logged into the ReST API. In theory, if you have the LLCookie for one, you have the authentication for the other. I verified this by taking the HTTP_COOKIE value from my UI browse request in CS Builder, performed a Web.Escape on the string, then pasted the escaped string into my otcsheader in my Advanced REST Client for Chrome. That worked!

So why do I say not to pursue this (for the record, the response from developers at the Partner Deep dive suggested the same)? The LLCookie is an HTTP-only cookie (or if it isn't it damned well should be). Javascript won't have access to it, so your ReST client wouldn't either.

I did consider that perhaps the key was to always authenticate with the REST API first, then somehow push that token to the LLCookie. So far, I haven't found a way of creating HTTP only cookies from Javascript and from a quick scan of Stack-Overflow, it looks like you shouldn't be able to do this.

Theoretically, a REST client developer might do a hybrid solution. After getting the authentication token, perhaps encrypting it some more and putting it in a regular cookie and customizing the standard ExecuteWithLogin on the Request handler object to grab that, decrypt it, and store it in LLCookie going forward. That is, the ReST client is the gatekeeper of authentication, and CS UI is the slave. It strikes me that this would be a more invasive customization than just doing what you need as a module containing web-lingos, and by exposing the authentication token, even encrypted, adds on to your security woes.

So, it appears that as cool as the ReST API is (I've been having a lot of fun playing with it, BTW), for folks who use the standard UI, offer them changes using Web Reports, ActiveViews, Appearances, or good old-fashioned Oscript :) If I'm talking complete smack, I hope someone points it out.
-Hugh

Tagged:

Comments

  • You write about the authentication problem only. I see it exactly the other way round. In comparison with SAP, Oracle or SharePoint portals, the CS as an application portal has a huge benefit - you log in to the CS and you get the ticket for the REST API "automatically". No problem with a second login and configuring SSO. In other portals you'd have to build the trust with the CS somehow first to enable SSO, or implement impersonation, or suffer the second login to the CS.

    You need nothing so complicated as you described. You can have the OTCSTicket (LLCookie) available on the web page as window.otcsticket, for example, as noted here. Now you'd have do it by your WebLingo, which is surprisingly easy - one line of code. but I expect it available on every page generated by some common WebLingo in the future.

    Generally, I agree that there are other tools better for the CS UI customization, which you listed. The classical CS UI pages are based on the server-side page generation and there are extensibility point available when following this scenario. When you create an extension working as a browser application talking to the server by REST API asynchronously when necessary, it may not fit with the rest of the functionality. I don't say that it should be avoided; I believe that there are extensions (facets) where REST API has advantage. You should have a look what you want to achieve and sometimes use the server-side CS UI extension hooks or buy ActiveViews, which leverages them, but sometimes use jQuery + REST API, if it benefits the goal.

  • For quick changes to the CS UI, I have used jQuery within an appearance. I am curious though if embedding the otcsticket anywhere which is exposed to the javascript API makes the service vulnerable to cross-scripting (i.e. malicious code in an html posting).

  • If you already have an appearance (WebLingo) with jQuery, you can add this line there:

    <script type="text/javascript">
      window.otcsticket='`%S$MYOSPACE.Utils.GetOTCSTicketForRequestHandler(this)`';
    </script>
    

    Supported by your utility function like the following one. A function like this should be added to a core ospace; RESTAPI, CSUI or WEBLL. More about this below.

    object MYOSPACE::Utils
      string function GetOTCSTicketForRequestHandler(Object requestHandler)
        // As soon as the REST API uses its own ticket, this will change
        return requestHandler.fCookieData(requestHandler.fCookieName)
      end
    end
    

    Having the OTCSTicket exposed to JavaScript on the page makes neither the page nor the REST API vulnerable to the XSS. What does it mean having the OTCSTicket exposed to JavaScript then? If you have a page vulnerable to then XSS and the attacker gains access to it, they will be able to steal one more piece of information - the OTCSTicket.

    It is a general issue of browser applications, which have to place application keys, secrets and authorization tokens on the page, so that the JavaScript can use them to communicate with REST services. That is why it has become so important guarding against XSS, using SSL all the time and being able to revoke access for an application acting on your behalf. Additionally, it is the reason, why different APIs should use different authorization tickets; if the attacker breaks into one application, the ticket they gain access to should not allow them contact other systems. That is why using the LLCookie in the REST API increases the risk when the security is breached. This has been recognized and the value and will be replaced by some ticket specific to the REST API. The code sample above will work now as a workaround. Such method should be exposed by the REST API subsystem and become an interface that you can continue using regardless how the ticket is going to be computed in the future.

    You may think that if the REST API was authenticated by a HTTP-only cookie, there would be no need for exposing the ticket to JavaScript. However, that would make the API vulnerable to another kind of the XSS - another page (tab) could communicate asynchronously with the REST API on your behalf without you knowing about it, because you logged in on the first tab in your browser. Cookies are sent to the server in AJAX calls too in any browser tab; just the target (API) URL is important; not the source page URL. That is why every (application) page should let the user authorize access to a service on their behalf. If you don't want to annoy the user in the enterprise environment, you implement SSO, where the servers trust each other, but you don't make the API use cookies.

    Again, the reason why the REST API may not be the universal way to extend the classical CS UI is not the authentication, but the different nature of web applications based on server generated pages and web applications running in the web browser using REST APIs.

  • Quick question on your response: I had no idea that Oscript could be exposed in an Appearance (I'm talking core Content Server Appearances, not custom web-lingo), or are you suggesting an edit to one of the weblingo files used by apeparances?
    -Hugh

  • I might've confused in with the appearances, which use the technique of injecting a header component on the pages, but I'm not sure if you can use WebLingo in there.

    This would be the way how to do it in your module: orphan WEBNODE:HTMLComponents and point it to your WebLingo file. Set features of the orphan similarly to APPEARANCES:Appearance Header Component. The HTML fragment generated by the WebLingo will appear on every page, where the header is enabled in the GUI components of the request handler.

  • Ha! I thought orphaning would come into this sooner or later :)
    -Hugh

  • Clarke
    edited April 22, 2022 #8
    Options


    I too wanted to run add some JavaScript to a Appearance and make a Custom REST call.

    Despite the awesome power of ActiveView, an Appearance is still the best option to jamming something onto the Classic UI Multi-Select bar.

    As noted though, unlike AV/WR there is no ticket.

    I solved this problem by including a link to a WR in my Appearance:

    <SCRIPT type="text/javascript" SRC="/otcs/llisapi.dll?func=ll&objId=102940&objAction=RunReport"></SCRIPT>


    Here is 102940:

    [LL_WEBREPORT_EXCLUDEHTML /]

    function getTicket()

    {

       var ticket = '[LL_REPTAG_OTCSTICKET /]';

       return ticket;

    }


    Now I get call getTicket in my Appearance JS code (and then use the REST API with it).


    No need for Modules and WebLingo after all.



    Regards,

    -MC