Skip to content

Commit f9d8bcf

Browse files
[IIIF-188] configure headers adaptions for allowed origins on IIIF viewer
1 parent 88a8194 commit f9d8bcf

4 files changed

Lines changed: 44 additions & 0 deletions

File tree

server.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ const DIST_FOLDER = join(process.cwd(), 'dist/browser');
6565
// Set path fir IIIF viewer.
6666
const IIIF_VIEWER = join(process.cwd(), 'dist/iiif');
6767

68+
const miradorHtml = join(IIIF_VIEWER, '/mirador/index.html');
69+
6870
const indexHtml = join(DIST_FOLDER, 'index.html');
6971

7072
const cookieParser = require('cookie-parser');
@@ -86,6 +88,8 @@ const _window = domino.createWindow(indexHtml);
8688
// The REST server base URL
8789
const REST_BASE_URL = environment.rest.ssrBaseUrl || environment.rest.baseUrl;
8890

91+
const IIIF_ALLOWED_ORIGINS = environment.mirador.allowedOrigins;
92+
8993
// Assign the DOM window and document objects to the global object
9094
(_window as any).screen = {deviceXDPI: 0, logicalXDPI: 0};
9195
(global as any).window = _window;
@@ -231,6 +235,35 @@ export function app() {
231235
*/
232236
router.use('/iiif', express.static(IIIF_VIEWER, { index: false }));
233237

238+
/*
239+
* Adapt headers to allow embedding of IIIF viewer in authorized pages
240+
*/
241+
server.get('/iiif/mirador/index.html', (req, res) => {
242+
const referer = req.headers.referer;
243+
244+
if(referer && !referer.startsWith('/')) {
245+
try {
246+
const origin = new URL(referer).origin;
247+
if (isIiifAllowedOrigin(origin)) {
248+
console.info('Found allowed origin, setting headers for IIIF viewer');
249+
// CORS header
250+
res.setHeader('Access-Control-Allow-Origin', origin);
251+
// CSP for iframe embedding
252+
res.setHeader('Content-Security-Policy', `frame-ancestors ${origin};`);
253+
console.info('Headers have been set ', res.getHeader('Access-Control-Allow-Origin'), res.getHeader('Content-Security-Policy'));
254+
}
255+
} catch (error) {
256+
console.error("An error occurred setting security headers in response:", error.message);
257+
}
258+
}
259+
260+
res.sendFile(miradorHtml, (err) => {
261+
if (err) {
262+
res.status(500).send('Internal Server Error');
263+
}
264+
});
265+
});
266+
234267
/**
235268
* Checking server status
236269
*/
@@ -665,6 +698,14 @@ function healthCheck(req, res) {
665698
});
666699
});
667700
}
701+
702+
/*
703+
* Helper to determine if the origin is allowed
704+
*/
705+
function isIiifAllowedOrigin(origin) {
706+
return origin === REST_BASE_URL.replace("/server", "") || IIIF_ALLOWED_ORIGINS.includes(origin);
707+
}
708+
668709
// Webpack will replace 'require' with '__webpack_require__'
669710
// '__non_webpack_require__' is a proxy to Node 'require'
670711
// The below code is to ensure that the server is run only when not requiring the bundle.

src/config/default-app-config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ export class DefaultAppConfig implements AppConfig {
816816

817817
mirador: MiradorConfig = {
818818
enableDownloadPlugin: true,
819+
allowedOrigins: []
819820
};
820821

821822
loader: LoaderConfig = {

src/config/mirador-config.interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ import { Config } from './config.interface';
22

33
export interface MiradorConfig extends Config {
44
enableDownloadPlugin: boolean;
5+
allowedOrigins: string[];
56
}

src/environments/environment.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ export const environment: BuildConfig = {
603603

604604
mirador: {
605605
enableDownloadPlugin: true,
606+
allowedOrigins: []
606607
},
607608

608609
loader: {

0 commit comments

Comments
 (0)