Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #8 - Thumbnail not loading when media is private #9

Merged
merged 2 commits into from
Jul 10, 2023

Conversation

amym-li
Copy link
Contributor

@amym-li amym-li commented Jul 7, 2023

The Mirador Viewer uses img tags for thumbnails with direct links to the iiif server, so requests made to retrieve the thumbnail images do not contain authorization and token headers. This causes the thumbnails to not load when the media is private.

This PR uses a service worker to add the authorization and token headers to the img requests.

Resources

1. Creating the service worker file:

See: https://www.twelve21.io/how-to-access-images-securely-with-oauth-2-0/

js/service_worker.js

self.addEventListener('activate', function (event) {
  console.log('Service Worker: claiming control...');
  return self.clients.claim();
});

self.addEventListener('fetch', function (event) {
  if (event.request.destination === "image" && new URL(event.request.url).pathname.startsWith('/cantaloupe/iiif/') && new URL(location).searchParams.has('token')) {
    console.log('Service Worker: fetching...');
    var token = new URL(location).searchParams.get('token');
    event.respondWith(
      fetch(event.request, {
        headers: {
          'Authorization': 'Bearer ' + token,
          'token': token
        },
        mode: "cors",
        credentials: "include"
      })
    );
  }
});

2. Setting the 'Service-Worker-Allowed' header

By default, the scope of the service worker must be within the directory containing the service worker script. (The scope refers to the pages making the requests that are then intercepted by the service worker). However, in order to set the scope to /, the service_worker.js file would need to be moved into the root directory of the site. To set the scope outside of the script's directory, the Service-Worker-Allowed header needs to be added to the HTTP response when the service worker script is requested. This was done by creating a controller that provides the script and appends the header in its response, and then creating a /islandora_mirador_service_worker route which is used as the script URL when registering the service worker.

See: https://drupal.stackexchange.com/questions/307079/how-to-return-service-worker-with-custom-http-header-from-custom-module

src/Controller/ServiceWorkerController.php

class ServiceWorkerController extends ControllerBase {

...

  /**
   * Adds headers to the HTTP response.
   */
  public function serve(Request $request) {
    // path to service_worker.js
    $file_str = $this->extensionPathResolver->getPath('module', 'islandora_mirador') . '/js/service_worker.js';
    if (file_exists($file_str)) {
      // adding headers to response
      $response = new BinaryFileResponse($file_str, 200);
      $response->headers->set('Content-Type', 'application/javascript');
      $response->headers->set('Service-Worker-Allowed', '/');
      return $response;
    }
    throw new NotFoundHttpException();
  }

}

islandora_mirador.routing.yml

...
islandora_mirador.service_worker:
  path: '/islandora_mirador_service_worker'
  defaults: 
    _controller: '\Drupal\islandora_mirador\Controller\ServiceWorkerController::serve' 
  requirements: 
    _permission: 'access content'
...

3. Registering the service worker

See: https://www.twelve21.io/how-to-access-images-securely-with-oauth-2-0/

js/mirador_viewer.js

...
if ('serviceWorker' in navigator) {
      window.addEventListener('load', () => {
            navigator.serviceWorker
                  // using the service worker route
                  .register('/islandora_mirador_service_worker?token=' + settings.token, { scope: '/' })
                  .then(registration => {
                        console.log('ServiceWorker registration successful with scope: ', registration.scope);
                  })
                  .catch(err => {
                        console.log('ServiceWorker registration failed: ', err);
                  });
      });
}
...

amym-li added 2 commits July 7, 2023 11:47
The headers were added using a service worker.

For creating the service worker:
https://www.twelve21.io/how-to-access-images-securely-with-oauth-2-0/

Adding custom HTTP headers to the service worker script response:
By default, the scope of the service worker (the pages making the requests that are then intercepted by the service worker)
is required to be within the directory containing the service worker script. To set the scope outside of the script's
directory, the 'Service-Worker-Allowed' header needs to be added to the response when the service worker script is requested.
https://drupal.stackexchange.com/questions/307079/how-to-return-service-worker-with-custom-http-header-from-custom-module
FILE: /home/amy/dsu/isle-dc/codebase/web/modules/contrib/islandora_mirador/src/Controller/ServiceWorkerController.php
---------------------------------------------------------------------------------------------------------------------
FOUND 0 ERRORS AND 1 WARNING AFFECTING 1 LINE
---------------------------------------------------------------------------------------------------------------------
 19 | WARNING | \Drupal calls should be avoided in classes, use dependency injection instead
---------------------------------------------------------------------------------------------------------------------
@amym-li amym-li marked this pull request as ready for review July 7, 2023 17:40
@amym-li amym-li linked an issue Jul 7, 2023 that may be closed by this pull request
@kylehuynh205 kylehuynh205 merged commit 9416496 into drupal_mirador Jul 10, 2023
kylehuynh205 added a commit that referenced this pull request Jul 10, 2023
Include access control modules and configs into islandora Lite build
Enable Private file system by default
kylehuynh205 pushed a commit that referenced this pull request Dec 3, 2024
Move entity view displays to optional configs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Thumbnail is not loading when media is in Private mode
2 participants