Orthanc Explorer / Web Viewer - How to pass custom auth tokens

Hello All,

I’m looking into using a reverse proxy to control access to resources in Orthanc and allow external authentication, which was suggested in one of the articles in the Orthanc documentation. The proxy that I’m using has HTTP bearer token authentication. Once the user logs in then the token can be inspected in each of the REST requests to block any unauthorized requests. However, the explorer and web viewer would need to pass the authentication header with the token for each REST request coming from the web browser.

Since both the explorer and web viewer are single page web apps it might be possible to pass the authorization token after the user logs in via a query parameter to the page that is then added to each REST request made by that page.

Alternatively, the explorer can be extended using a plugin that uses a jquery interceptor to add the authorization header. There doesn’t seem to be a similar mechanism to add javascript the web viewer though. Perhaps, the web viewer could accept similar contributions from plugins?

There might be some other way to handle this that I had not considered. Has anyone else run into this situation?

I can look into creating and submitting source code patches to this project if needed.

Thank you,
Chris

Hello,

There has been several discussions in the past on that topic in the forum, e.g.:
https://groups.google.com/d/msg/orthanc-users/YqJXdPjscXo/ETphu7LcBQAJ

https://groups.google.com/d/msg/orthanc-users/qw0JidNtMoM/g6yoH3WOBAAJ

You might also have an interest in the authorization plugin:
https://book.orthanc-server.com/plugins/authorization.html

However, questions about authorization are handled by Alain. Please wait for his answer in the following next weeks.

Regards,
Sébastien-

Thanks Sébastien,

I saw those threads. I think that my case is a little different. Sorry to re-hash the same conversation if it’s not.

I’m using the Orthanc explorer and web viewer, not the Osimis one. My authenticating reverse proxy is in front so that no unauthorized traffic makes it to Orthanc and we can load balance in the future. The authentication plugin doesn’t seem to support this workflow as far as I can tell from the documentation. I’ll wait and see if Alain has more information.

Cheers,
Chris

Hi Chris,

Indeed, it was not possible to pass an auth token to the Orthanc Explorer or the Orthanc viewer via the url search params.

I’ve just implemented it and this will be available in the next releases (1.5.8).

You can now open the Orthanc explorer on http://localhost:8042/app/explorer.html?token=1234 and this token will be included as an HTTP header in every request sent to the Rest API. It will also be included in the url when opening the Orthanc or Osimis viewer. This should simplify the use of the Orthanc Authorization plugin.

HTH

Alain.

Hi Alain,

Thank you for getting back to me and making this functionality available.

After giving the problem a bit more thought I realized that putting authentication tokens in the URL is a security anti-pattern, unfortunately. I recalled from my security training that the problem with putting any kind of authentication information in the URL is that they get bookmarked and shared. Users don't usually anticipate the need to strip the query information out manually. Also, URL's are not generally considered in any browser cross origin safety checks, such as CORS. Unfortunately, this makes the problem of custom auth token sharing harder.

I've since moved to using a fully custom UI and viewer for a few reasons, which I think is what is the recommendation anyway. Before I made that decision I experimented with a mechanism that would allow the token to be shared outside of the URL. I am providing some information here from my investigation in case it is helpful to this project or other Orthanc users out there.

When the Orthanc viewer or explorer is opened with a special query parameter (e.g. "?token=listen") it can wait for a message coming to the browser window using a callback before allowing the viewer to initialize and begin doing the REST requests that it normally does. Once the message is received with the token all REST requests on the page can be intercepted so that the auth header is added every time.

Inter-window messaging is described here:
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

The Orthanc viewer and explorer use jQuery, which allows you to pause the page startup so that it can wait for the auth token before it starts invoking any $(document).ready() callbacks to initialize the page start the processes that involve making REST requests to the server.
$.holdReady( true );

Then the viewer and explorer can wait for the messages like this:
window.addEventListener('message', function(event) {
    <authTokenVar> = event.data.authToken;
    $.holdReady(false); // Resume page load now that we have the token
}, false);

jQuery also has an interceptor capability for all REST requests so that once the page has the auth token it can put that in the request header regardless of where it is used on the page.
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    options.headers = {
      'Authorization': <authTokenVar>
    };
  });

But, there is a race condition between when the caller opens the window (or navigates it) to load the explorer and the page is ready to receive the message. A solution that I found was to have the caller open the window and then wait for the load event before sending the message. This gives the page the chance to set up to receive the auth token message. Once the load event is received by the caller it can then send the authorization token using postMessage.
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload

Note that if this kind of support were ever added to the explorer or the viewer, they should probably have safeguards against malicious origins of window messages. When receiving the auth token message they should consult allowable origins in the orthanc config (orthanc.json) file and block any unrecognized origins as a safety precaution.

I hope that this is helpful.

Thanks again,
Chris