diff --git a/__tests__/src/selectors/auth.test.js b/__tests__/src/selectors/auth.test.js
index 698b32115d1c2f8986e10b482660c19dcef7624f..2071e993177a68d8b536f9aade9d58971914c2d3 100644
--- a/__tests__/src/selectors/auth.test.js
+++ b/__tests__/src/selectors/auth.test.js
@@ -1,5 +1,9 @@
+import manifestFixture001 from '../../fixtures/version-2/001.json';
+import manifestFixture019 from '../../fixtures/version-2/019.json';
+import settings from '../../../src/config/settings';
 import {
   getAccessTokens,
+  selectCurrentAuthServices,
 } from '../../../src/state/selectors/auth';
 
 describe('getAccessTokens', () => {
@@ -16,3 +20,178 @@ describe('getAccessTokens', () => {
     expect(accessTokens).toEqual(state.accessTokens);
   });
 });
+
+describe('selectCurrentAuthServices', () => {
+  const resource = {
+    service: [
+      {
+        '@id': 'external',
+        profile: 'http://iiif.io/api/auth/1/external',
+      },
+      {
+        '@id': 'login',
+        profile: 'http://iiif.io/api/auth/1/login',
+      },
+    ],
+  };
+  const externalOnly = {
+    service: [
+      {
+        '@id': 'external',
+        profile: 'http://iiif.io/api/auth/1/external',
+      },
+    ],
+  };
+
+  const state = {
+    auth: {},
+    config: { auth: settings.auth },
+    infoResponses: {
+      'https://iiif.bodleian.ox.ac.uk/iiif/image/9cca8fdd-4a61-4429-8ac1-f648764b4d6d': {
+        json: resource,
+      },
+      'https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44': {
+        json: externalOnly,
+      },
+    },
+    manifests: {
+      a: {
+        json: manifestFixture001,
+      },
+      b: {
+        json: manifestFixture019,
+      },
+    },
+    windows: {
+      noCanvas: {
+        manifestId: 'a',
+      },
+      w: {
+        manifestId: 'a',
+        visibleCanvases: [
+          'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json',
+        ],
+      },
+      x: {
+        manifestId: 'b',
+        visibleCanvases: [
+          'http://iiif.io/api/presentation/2.0/example/fixtures/canvas/24/c1.json',
+        ],
+      },
+      y: {
+        manifestId: 'b',
+        visibleCanvases: [
+          'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1',
+        ],
+      },
+    },
+  };
+
+  it('returns undefined if there is no current canvas', () => {
+    expect(selectCurrentAuthServices({ config: { auth: settings.auth }, manifests: {} }, { windowId: 'noCanvas' })[0]).toBeUndefined();
+  });
+
+  it('returns the next auth service to try', () => {
+    expect(selectCurrentAuthServices(state, { windowId: 'w' })[0].id).toEqual('external');
+  });
+
+  it('returns the service if the next auth service is interactive', () => {
+    const auth = { external: { isFetching: false, ok: false } };
+    expect(selectCurrentAuthServices({ ...state, auth }, { windowId: 'w' })[0].id).toEqual('login');
+  });
+
+  it('returns the last attempted auth service if all of them have been tried', () => {
+    const auth = {
+      external: { isFetching: false, ok: false },
+      login: { isFetching: false, ok: false },
+    };
+    expect(selectCurrentAuthServices({ ...state, auth }, { windowId: 'w' })[0].id).toEqual('login');
+    expect(selectCurrentAuthServices({ ...state, auth }, { windowId: 'x' })[0].id).toEqual('external');
+    expect(selectCurrentAuthServices({ ...state, auth }, { windowId: 'y' })[0]).toBeUndefined();
+  });
+
+  describe('proscribed order', () => {
+    let auth = {};
+    const orderedState = {
+      config: { auth: settings.auth },
+      infoResponses: {
+        'https://iiif.bodleian.ox.ac.uk/iiif/image/9cca8fdd-4a61-4429-8ac1-f648764b4d6d': {
+          json: {
+            service: [
+              {
+                '@id': 'external',
+                profile: 'http://iiif.io/api/auth/1/external',
+              },
+              {
+                '@id': 'kiosk',
+                profile: 'http://iiif.io/api/auth/1/kiosk',
+              },
+              {
+                '@id': 'clickthrough',
+                profile: 'http://iiif.io/api/auth/1/clickthrough',
+              },
+              {
+                '@id': 'login',
+                profile: 'http://iiif.io/api/auth/1/login',
+              },
+              {
+                '@id': 'login2',
+                profile: 'http://iiif.io/api/auth/1/login',
+              },
+            ],
+          },
+        },
+      },
+      manifests: {
+        a: {
+          json: manifestFixture001,
+        },
+      },
+      windows: {
+        w: {
+          manifestId: 'a',
+          visibleCanvases: [
+            'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json',
+          ],
+        },
+      },
+    };
+
+    it('returns external first', () => {
+      auth = {};
+      expect(selectCurrentAuthServices({ ...orderedState, auth }, { windowId: 'w' })[0].id).toEqual('external');
+    });
+
+    it('returns kiosk next', () => {
+      auth = { external: { isFetching: false, ok: false } };
+      expect(selectCurrentAuthServices({ ...orderedState, auth }, { windowId: 'w' })[0].id).toEqual('kiosk');
+    });
+
+    it('returns clickthrough next', () => {
+      auth = {
+        external: { isFetching: false, ok: false },
+        kiosk: { isFetching: false, ok: false },
+      };
+      expect(selectCurrentAuthServices({ ...orderedState, auth }, { windowId: 'w' })[0].id).toEqual('clickthrough');
+    });
+
+    it('returns logins last', () => {
+      auth = {
+        clickthrough: { isFetching: false, ok: false },
+        external: { isFetching: false, ok: false },
+        kiosk: { isFetching: false, ok: false },
+      };
+      expect(selectCurrentAuthServices({ ...orderedState, auth }, { windowId: 'w' })[0].id).toEqual('login');
+    });
+
+    it('returns services within a given type using the order from the manifest', () => {
+      auth = {
+        clickthrough: { isFetching: false, ok: false },
+        external: { isFetching: false, ok: false },
+        kiosk: { isFetching: false, ok: false },
+        login: { isFetching: false, ok: false },
+      };
+      expect(selectCurrentAuthServices({ ...orderedState, auth }, { windowId: 'w' })[0].id).toEqual('login2');
+    });
+  });
+});
diff --git a/__tests__/src/selectors/canvases.test.js b/__tests__/src/selectors/canvases.test.js
index b318e19ed95505d975c56fdbd525ae7a15d5378f..c6dcf8145bbf416670ddda930b6dcffe04cd8a93 100644
--- a/__tests__/src/selectors/canvases.test.js
+++ b/__tests__/src/selectors/canvases.test.js
@@ -10,7 +10,6 @@ import {
   getPreviousCanvasGrouping,
   getCanvas,
   getCanvasLabel,
-  selectCanvasAuthService,
   selectInfoResponse,
   getVisibleCanvasNonTiledResources,
   getVisibleCanvasIds,
@@ -250,150 +249,6 @@ describe('getCanvasLabel', () => {
   });
 });
 
-describe('selectCanvasAuthService', () => {
-  const resource = {
-    service: [
-      {
-        '@id': 'external',
-        profile: 'http://iiif.io/api/auth/1/external',
-      },
-      {
-        '@id': 'login',
-        profile: 'http://iiif.io/api/auth/1/login',
-      },
-    ],
-  };
-  const externalOnly = {
-    service: [
-      {
-        '@id': 'external',
-        profile: 'http://iiif.io/api/auth/1/external',
-      },
-    ],
-  };
-
-  const state = {
-    auth: {},
-    config: { auth: settings.auth },
-    infoResponses: {
-      'https://iiif.bodleian.ox.ac.uk/iiif/image/9cca8fdd-4a61-4429-8ac1-f648764b4d6d': {
-        json: resource,
-      },
-      'https://stacks.stanford.edu/image/iiif/hg676jb4964%2F0380_796-44': {
-        json: externalOnly,
-      },
-    },
-    manifests: {
-      a: {
-        json: manifestFixture001,
-      },
-      b: {
-        json: manifestFixture019,
-      },
-    },
-  };
-
-  it('returns undefined if there is no current canvas', () => {
-    expect(selectCanvasAuthService({ config: { auth: settings.auth }, manifests: {} }, { manifestId: 'a' })).toBeUndefined();
-  });
-
-  it('returns the next auth service to try', () => {
-    expect(selectCanvasAuthService(state, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('external');
-  });
-
-  it('returns the service if the next auth service is interactive', () => {
-    const auth = { external: { isFetching: false, ok: false } };
-    expect(selectCanvasAuthService({ ...state, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('login');
-  });
-
-  it('returns the last attempted auth service if all of them have been tried', () => {
-    const auth = {
-      external: { isFetching: false, ok: false },
-      login: { isFetching: false, ok: false },
-    };
-    expect(selectCanvasAuthService({ ...state, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('login');
-    expect(selectCanvasAuthService({ ...state, auth }, { canvasId: 'http://iiif.io/api/presentation/2.0/example/fixtures/canvas/24/c1.json', manifestId: 'b' }).id).toEqual('external');
-    expect(selectCanvasAuthService({ ...state, auth }, { canvasId: 'https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1', manifestId: 'b' })).toBeUndefined();
-  });
-
-  describe('proscribed order', () => {
-    let auth = {};
-    const orderedState = {
-      config: { auth: settings.auth },
-      infoResponses: {
-        'https://iiif.bodleian.ox.ac.uk/iiif/image/9cca8fdd-4a61-4429-8ac1-f648764b4d6d': {
-          json: {
-            service: [
-              {
-                '@id': 'external',
-                profile: 'http://iiif.io/api/auth/1/external',
-              },
-              {
-                '@id': 'kiosk',
-                profile: 'http://iiif.io/api/auth/1/kiosk',
-              },
-              {
-                '@id': 'clickthrough',
-                profile: 'http://iiif.io/api/auth/1/clickthrough',
-              },
-              {
-                '@id': 'login',
-                profile: 'http://iiif.io/api/auth/1/login',
-              },
-              {
-                '@id': 'login2',
-                profile: 'http://iiif.io/api/auth/1/login',
-              },
-            ],
-          },
-        },
-      },
-      manifests: {
-        a: {
-          json: manifestFixture001,
-        },
-      },
-    };
-
-    it('returns external first', () => {
-      auth = {};
-      expect(selectCanvasAuthService({ ...orderedState, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('external');
-    });
-
-    it('returns kiosk next', () => {
-      auth = { external: { isFetching: false, ok: false } };
-      expect(selectCanvasAuthService({ ...orderedState, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('kiosk');
-    });
-
-    it('returns clickthrough next', () => {
-      auth = {
-        external: { isFetching: false, ok: false },
-        kiosk: { isFetching: false, ok: false },
-      };
-      expect(selectCanvasAuthService({ ...orderedState, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('clickthrough');
-    });
-
-    it('returns logins last', () => {
-      auth = {
-        clickthrough: { isFetching: false, ok: false },
-        external: { isFetching: false, ok: false },
-        kiosk: { isFetching: false, ok: false },
-      };
-      expect(selectCanvasAuthService({ ...orderedState, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('login');
-    });
-
-    it('returns services within a given type using the order from the manifest', () => {
-      auth = {
-        clickthrough: { isFetching: false, ok: false },
-        external: { isFetching: false, ok: false },
-        kiosk: { isFetching: false, ok: false },
-        login: { isFetching: false, ok: false },
-      };
-      expect(selectCanvasAuthService({ ...orderedState, auth }, { canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/9cca8fdd-4a61-4429-8ac1-f648764b4d6d.json', manifestId: 'a' }).id).toEqual('login2');
-    });
-  });
-});
-
 describe('selectInfoResponse', () => {
   it('returns in the info response for the first canvas resource', () => {
     const resource = { some: 'resource' };
diff --git a/src/containers/IIIFAuthentication.js b/src/containers/IIIFAuthentication.js
index f1cd7f0db3f83006b87d0c2ab56533e1a5739984..eac81a4e861a2045a7309227f839af8bb8918e66 100644
--- a/src/containers/IIIFAuthentication.js
+++ b/src/containers/IIIFAuthentication.js
@@ -5,10 +5,9 @@ import { Utils } from 'manifesto.js/dist-esmodule/Utils';
 import { withPlugins } from '../extend/withPlugins';
 import * as actions from '../state/actions';
 import {
-  getCurrentCanvas,
   getAuth,
-  isInteractiveAuth,
-  selectCanvasAuthService,
+  getAuthProfiles,
+  selectCurrentAuthServices,
   getAccessTokens,
 } from '../state/selectors';
 import { IIIFAuthentication } from '../components/IIIFAuthentication';
@@ -19,8 +18,10 @@ import { IIIFAuthentication } from '../components/IIIFAuthentication';
  * @private
  */
 const mapStateToProps = (state, { windowId }) => {
-  const canvasId = (getCurrentCanvas(state, { windowId }) || {}).id;
-  const service = selectCanvasAuthService(state, { canvasId, windowId });
+  const services = selectCurrentAuthServices(state, { windowId });
+
+  // TODO: get the most actionable auth service...
+  const service = services[0];
 
   const accessTokenService = service && (
     Utils.getService(service, 'http://iiif.io/api/auth/1/token')
@@ -31,12 +32,10 @@ const mapStateToProps = (state, { windowId }) => {
     || Utils.getService(service, 'http://iiif.io/api/auth/0/logout')
   );
 
-  const authStatuses = getAuth(state) || {};
+  const authStatuses = getAuth(state);
   const authStatus = service && authStatuses[service.id];
-  const accessTokens = authStatus && accessTokenService && getAccessTokens(state);
-  const accessTokenStatus = accessTokens && Object.values(accessTokens).find(
-    e => e.id === accessTokenService.id,
-  );
+  const accessTokens = getAccessTokens(state);
+  const accessTokenStatus = accessTokenService && accessTokens[accessTokenService.id];
 
   let status;
 
@@ -45,18 +44,20 @@ const mapStateToProps = (state, { windowId }) => {
   } else if (authStatus.ok) {
     status = 'ok';
   } else if (authStatus.isFetching) {
-    if (authStatus.windowId === windowId) {
-      status = 'cookie';
-    }
+    if (authStatus.windowId === windowId) status = 'cookie';
   } else if (accessTokenStatus && accessTokenStatus.isFetching) {
-    if (authStatus.windowId === windowId) {
-      status = 'token';
-    }
+    if (authStatus.windowId === windowId) status = 'token';
   } else {
     status = 'failed';
   }
 
-  const isInteractive = isInteractiveAuth(state, { canvasId, windowId });
+  const authProfiles = getAuthProfiles(state);
+
+  const profile = service && service.getProfile();
+
+  const isInteractive = authProfiles.some(
+    config => config.profile === profile && !(config.external || config.kiosk),
+  );
 
   return {
     accessTokenServiceId: accessTokenService && accessTokenService.id,
@@ -69,7 +70,7 @@ const mapStateToProps = (state, { windowId }) => {
     isInteractive,
     label: service && service.getLabel()[0].value,
     logoutServiceId: logoutService && logoutService.id,
-    profile: service && service.getProfile(),
+    profile,
     status,
   };
 };
diff --git a/src/state/selectors/auth.js b/src/state/selectors/auth.js
index 5e63c387ac41e8b46028e7bcdeab84331eeda438..0345021475d3f710a504ba520cc6c26ddae20851 100644
--- a/src/state/selectors/auth.js
+++ b/src/state/selectors/auth.js
@@ -1,9 +1,17 @@
 import { createSelector } from 'reselect';
 import { Utils } from 'manifesto.js/dist-esmodule/Utils';
+import flatten from 'lodash/flatten';
 import MiradorCanvas from '../../lib/MiradorCanvas';
 import { miradorSlice } from './utils';
 import { getConfig } from './config';
-import { selectInfoResponse, getCanvas } from './canvases';
+import { getVisibleCanvases, selectInfoResponses } from './canvases';
+
+export const getAuthProfiles = createSelector(
+  [
+    getConfig,
+  ],
+  ({ auth: { serviceProfiles = [] } }) => serviceProfiles,
+);
 
 /** */
 export const getAccessTokens = state => miradorSlice(state).accessTokens || {};
@@ -11,72 +19,65 @@ export const getAccessTokens = state => miradorSlice(state).accessTokens || {};
 /** */
 export const getAuth = state => miradorSlice(state).auth || {};
 
-export const selectCanvasAuthService = createSelector(
+export const selectCurrentAuthServices = createSelector(
   [
-    selectInfoResponse,
-    getCanvas,
-    getConfig,
+    getVisibleCanvases,
+    selectInfoResponses,
+    getAuthProfiles,
     getAuth,
+    (state, { iiifResources }) => iiifResources,
   ],
-  (infoResponse, canvas, { auth: { serviceProfiles = [] } }, auth) => {
-    let iiifResource;
-    iiifResource = infoResponse && infoResponse.json && { ...infoResponse.json, options: {} };
+  (canvases, infoResponses = {}, serviceProfiles, auth, iiifResources) => {
+    let currentAuthResources = iiifResources;
 
-    if (!iiifResource && canvas) {
-      const miradorCanvas = new MiradorCanvas(canvas);
-      const [image] = miradorCanvas.iiifImageResources;
+    if (!currentAuthResources && canvases) {
+      currentAuthResources = flatten(canvases.map(c => {
+        const miradorCanvas = new MiradorCanvas(c);
+        const images = miradorCanvas.iiifImageResources;
 
-      iiifResource = image && image.getServices()[0];
-    }
+        return images.map(i => {
+          const iiifImageService = i.getServices()[0];
 
-    if (!iiifResource) return undefined;
+          const infoResponse = infoResponses[iiifImageService.id];
+          if (infoResponse && infoResponse.json) {
+            return { ...infoResponse.json, options: {} };
+          }
+
+          return iiifImageService;
+        });
+      }));
+    }
 
-    const orderedAuthServiceProfiles = serviceProfiles.map(p => p.profile);
+    if (!currentAuthResources) return [];
+    if (currentAuthResources.length === 0) return [];
 
-    let lastAttemptedService;
+    const currentAuthServices = currentAuthResources.map(resource => {
+      let lastAttemptedService;
+      const services = Utils.getServices(resource);
 
-    for (const profile of orderedAuthServiceProfiles) {
-      const services = getServices(iiifResource, profile);
-      for (const service of services) {
-        if (!auth[service.id]) return service;
+      for (const authProfile of serviceProfiles) {
+        const profiledAuthServices = services.filter(
+          p => authProfile.profile === p.getProfile(),
+        );
 
-        lastAttemptedService = service;
+        for (const service of profiledAuthServices) {
+          lastAttemptedService = service;
 
-        if (auth[service.id].isFetching || auth[service.id].ok) return service;
+          if (!auth[service.id] || auth[service.id].isFetching || auth[service.id].ok) {
+            return service;
+          }
+        }
       }
-    }
 
-    return lastAttemptedService;
-  },
-);
+      return lastAttemptedService;
+    });
 
-/** */
-export function selectAuthStatus({ auth }, service) {
-  if (!service) return null;
-  if (!auth[service.id]) return null;
-  if (auth[service.id].isFetching) return 'fetching';
-  if (auth[service.id].ok) return 'ok';
-  return 'failed';
-}
-
-/** Get all the services that match a profile */
-function getServices(resource, profile) {
-  const services = Utils.getServices(resource);
-
-  return services.filter(service => service.getProfile() === profile);
-}
-
-/** check if the current auth service is "interactive" */
-export const isInteractiveAuth = createSelector(
-  [
-    selectCanvasAuthService,
-    getConfig,
-  ],
-  (service, { auth: { serviceProfiles = [] } }) => {
-    const profile = service && service.getProfile();
+    return Object.values(currentAuthServices.reduce((h, service) => {
+      if (service && !h[service.id]) {
+        h[service.id] = service; // eslint-disable-line no-param-reassign
+      }
 
-    return serviceProfiles.some(
-      config => config.profile === profile && !(config.external || config.kiosk),
-    );
+      return h;
+    }, {}));
   },
 );