Skip to content

Commit 20c3e62

Browse files
[IIIF-188] configure headers adaptions for allowed origins on IIIF viewer
1 parent 92f527f commit 20c3e62

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
@@ -67,6 +67,8 @@ const DIST_FOLDER = join(process.cwd(), 'dist/browser');
6767
// Set path fir IIIF viewer.
6868
const IIIF_VIEWER = join(process.cwd(), 'dist/iiif');
6969

70+
const miradorHtml = join(IIIF_VIEWER, '/mirador/index.html');
71+
7072
const indexHtml = join(DIST_FOLDER, 'index.html');
7173

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

93+
const IIIF_ALLOWED_ORIGINS = environment.mirador.allowedOrigins;
94+
9195
// Assign the DOM window and document objects to the global object
9296
(_window as any).screen = {deviceXDPI: 0, logicalXDPI: 0};
9397
(global as any).window = _window;
@@ -211,6 +215,35 @@ export function app() {
211215
*/
212216
router.use('/iiif', express.static(IIIF_VIEWER, { index: false }));
213217

218+
/*
219+
* Adapt headers to allow embedding of IIIF viewer in authorized pages
220+
*/
221+
server.get('/iiif/mirador/index.html', (req, res) => {
222+
const referer = req.headers.referer;
223+
224+
if(referer && !referer.startsWith('/')) {
225+
try {
226+
const origin = new URL(referer).origin;
227+
if (isIiifAllowedOrigin(origin)) {
228+
console.info('Found allowed origin, setting headers for IIIF viewer');
229+
// CORS header
230+
res.setHeader('Access-Control-Allow-Origin', origin);
231+
// CSP for iframe embedding
232+
res.setHeader('Content-Security-Policy', `frame-ancestors ${origin};`);
233+
console.info('Headers have been set ', res.getHeader('Access-Control-Allow-Origin'), res.getHeader('Content-Security-Policy'));
234+
}
235+
} catch (error) {
236+
console.error("An error occurred setting security headers in response:", error.message);
237+
}
238+
}
239+
240+
res.sendFile(miradorHtml, (err) => {
241+
if (err) {
242+
res.status(500).send('Internal Server Error');
243+
}
244+
});
245+
});
246+
214247
/**
215248
* Checking server status
216249
*/
@@ -667,6 +700,14 @@ function healthCheck(req, res) {
667700
});
668701
});
669702
}
703+
704+
/*
705+
* Helper to determine if the origin is allowed
706+
*/
707+
function isIiifAllowedOrigin(origin) {
708+
return origin === REST_BASE_URL.replace("/server", "") || IIIF_ALLOWED_ORIGINS.includes(origin);
709+
}
710+
670711
// Webpack will replace 'require' with '__webpack_require__'
671712
// '__non_webpack_require__' is a proxy to Node 'require'
672713
// 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
@@ -943,6 +943,7 @@ export class DefaultAppConfig implements AppConfig {
943943

944944
mirador: MiradorConfig = {
945945
enableDownloadPlugin: true,
946+
allowedOrigins: []
946947
};
947948

948949
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
@@ -711,6 +711,7 @@ export const environment: BuildConfig = {
711711

712712
mirador: {
713713
enableDownloadPlugin: true,
714+
allowedOrigins: []
714715
},
715716

716717
loader: {

0 commit comments

Comments
 (0)