Viewers: Embedded viewer does not include Authorization headers when fetching dicom instances, stand-alone does

Bug Report

When setting up a requestOptions.auth element for dicomWeb in OHIF’s config, the embedded viewer only includes the Authorization header for GET requests to dicom-web/studies, dicom-web/studies/xxx/series and dicom-web/studies/xxx/series/yyyy/metadata.

Requests to studies/xxx/series/yyy/instances/zzz1/frames/1, studies/xxx/series/yyy/instances/zzz2/frames/1, etc. do not include the Authorization header. This leads to a 401 Unauthorized response from the dicom-web server.

I experience this using the latest ovif release via an embedded script pointing to https://unpkg.com/@ohif/viewer (see below). When I build OVIF for production, as per the documentation; so from latest master, the Authorization header is included and the instance requests receive a 200 response.

I’ve included two screenshots of the XHR requests of the embedded and the production viewer below. Embedded is on the left, production on the right. The first screenshot compares the CORS preflight requests. The second the actual requests for retrieving the dicom instances. Note that already in the CORS preflight requests, the Access-Control-Request-Headers header does not include authorization in the embedded viewer. It does in the standalone. In the actual requests, the authorization header is missing in the embedded viewer.

Describe the Bug

Embedded viewer does not include Authorization headers for dicom-web dicom instance requests

What steps can we follow to reproduce the bug?

  1. Setup an embedded ovif viewer coupled with a dicom-web server that expects Authorization (basic) headers
  2. Try to view a dicom series in the viewer
  3. The viewer fails to render, inspection of the network traffic reveals 401 Unauthorized responses
  <script src="https://unpkg.com/@ohif/viewer" crossorigin></script>
  <script>
    var containerId = "root";
    var componentRenderedOrUpdatedCallback = function(){
      console.log('OHIF Viewer rendered/updated');
    }

window.config = {
  // default: '/'
  routerBasename: '/',
  extensions: [],
  showStudyList: true,
  filterQueryParam: false,
  servers: {
    dicomWeb: [
      {
        name: 'scorthanc',
        wadoUriRoot: 'https://orthanc.yyy.zzz/orthanc/wado',
        qidoRoot: 'https://orthanc.yyy.zzz/orthanc/dicom-web',
        wadoRoot: 'https://orthanc.yyy.zzz/orthanc/dicom-web',
        qidoSupportsIncludeField: true,
        imageRendering: 'wadors',
        thumbnailRendering: 'wadors',
        requestOptions: {
          auth: 'user:password',
        },
      },
    ],
  },
  cornerstoneExtensionConfig: {},
  // Following property limits number of simultaneous series metadata requests.
  // For http/1.x-only servers, set this to 5 or less to improve
  //  on first meaningful display in viewer
  // If the server is particularly slow to respond to series metadata
  //  requests as it extracts the metadata from raw files everytime,
  //  try setting this to even lower value
  // Leave it undefined for no limit, sutiable for HTTP/2 enabled servers
  // maxConcurrentMetadataRequests: 5,
};

    window.OHIFViewer.installViewer(
      window.config, containerId, componentRenderedOrUpdatedCallback);
	</script>

Details of a preflight CORS request (embedded left, production build right): ovif-pre-flight

Details of a dcm instance request (embedded left, production build right): ovif-dcm-instance

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 21 (2 by maintainers)

Commits related to this issue

Most upvoted comments

https://github.com/OHIF/Viewers/blob/709f14708e2b0f912b5ea509114acd87af3149cb/platform/viewer/src/config.js#L45-L60

At line 47 I’ve managed to workaround this issue by passing to getAuthorizationHeader my dicomWeb configuration as follows:

const headers = OHIF.DICOMWeb.getAuthorizationHeader(appConfig.servers.dicomWeb[0]);

salam , in config.js try change this code : beforeSend: function(xhr) { const headers = OHIF.DICOMWeb.getAuthorizationHeader(); if (headers.Authorization) { xhr.setRequestHeader('Authorization', headers.Authorization); } }, to this : beforeSend: function (xhr) { debugger const state = window.store.getState(); const activeServer = state.servers.servers.find(t => t.active); const headers = OHIF.DICOMWeb.getAuthorizationHeader(activeServer); debugger if (headers.Authorization) { xhr.setRequestHeader('Authorization', headers.Authorization); } },

the answer is here: https://cloud.google.com/healthcare/docs/how-tos/authentication

I started a new firebase project from scratch. the usual way is to set an endpoint to retrieve it (your token). because you need to sign it using your service account RSA private key. so you need to keep it safe.

I used cloud functions with express for creating an api.

this.http.get(this.api + '/sign', { responseType: 'text' }).subscribe( result => this.token = result );

then you have to use the ‘requestOptions’ parameter on the ohif servers settings (remove odic);

requestOptions: {
                  auth: (options) => { return 'Bearer ' + this.token }
                }

token needs to be signed and include a valid date/expiration

see:

https://jwt.io/ https://firebase.google.com/docs/auth/admin/create-custom-tokens https://github.com/auth0/node-jsonwebtoken (used to sign the token)