Skip to content

IIIF Auth 2.0 Support

Dananji Withana edited this page Jul 2, 2026 · 7 revisions

Ramp supports the IIIF Authentication Flow API 2.0 for Canvases with media resource(s) that require authorization before playback. When a Canvas' Annotation body declares a service block containing an AuthProbeService2, Ramp renders a login overlay over the player and drives the probe -> access -> token exchange described by the spec before allowing playback to start.

Parsing Auth service Structure

Ramp reads and parses service property off the first Annotation's body for each Canvas. If the body property is a Choice (multiple source qualities/formats), the auth service is read from the first item in body.items, and Ramp assumes auth service information is identical across all choices in a single Canvas.

The nested auth service structure Probe → AccessService → [Token, Logout] is then parsed to:

  • AuthProbeService2 - as the top-level probe service. And is required for auth to be recognized
  • AuthAccessService2 — nested under the probe's own service array; only services with either 'active' or 'kiosk' are used
  • AuthAccessTokenService2 and AuthLogoutService2 — nested under the access service's service array

An example nested auth service block looks as follows;

"service": [
  {
    "id": "https://example.org/iiif/auth/probe",
    "type": "AuthProbeService2",
    "service": [
      {
        "id": "https://example.org/iiif/auth/login",
        "type": "AuthAccessService2",
        "profile": "active",
        "label": { "en": ["Login"] },
        "service": [
          { "id": "https://example.org/iiif/auth/token", "type": "AuthAccessTokenService2" },
          { "id": "https://example.org/iiif/auth/logout", "type": "AuthLogoutService2", "label": { "en": ["Sign out"] } }
        ]
      }
    ]
  }
]

If no AuthAccessService2 or no AuthAccessTokenService2 is found under the probe, the Canvas is flagged restricted: true and Ramp displays an error state instead of a login prompt, since there's no way to complete the auth flow.

Auth State in Ramp

Auth status for the currently active Canvas is tracked in the central state via Context Providers under state.auth: { token, status } property. The value of status moves through: idle -> probing -> login-required | authorized | error | cancelled. Auth state resets to idle on logout (see below), which re-triggers the initial probe to display the login prompt.

Auth UI and Workflow

Ramp follows the expected auth flow from a IIIF client detailed in the IIIF Auth spec 2.0.

login-prompt

AuthOverlay.js renders over the VideoJSPlayer whenever a Canvas has a non-restricted auth service, and drives the flow:

  1. Request probe on mount as an unauthenticated GET to the probe service's id. A 200 sets status to authorized; anything else sets login-required and the overlay renders the login prompt with descriptive properties available from the parsed access service.
  2. Request login when clicked on the Login button depending on the access service's profile:
    • kiosk — acquires a token immediately without a user interaction
    • active — opens the access service id in a new tab and polls every 500ms for the tab to close. If the browser blocks the popup, Ramp falls back to acquiring the token directly without opening a tab.
  3. Token acquisition appends a messageId and the client's origin to the token service URL, loads it in a hidden, iframe, and listens for a message event using post Message API where, a successful response resolves { accessToken, expiresIn }.
  4. Re-probe with the received token with Authorization: Bearer <token>. A 200 marks the Canvas authorized and stores the token in central state; otherwise the overlay shows an error using descriptive properties if the probe or token service provides it.

Cancelling mid-flow (closing the login tab manually, or clicking Cancel) clears the polling interval, closes any open login tab, and sets status to cancelled, dismissing the overlay without retrying.

Logout UI and Workflow

When the parsed access service defines an AuthLogoutService2, Ramp displays a logout control once the user is authorized. Per the logout interaction spec, the logout action button simply opens a new tab with the results of the HTTP GET request on the logout service’s URI in the browser, which is expected to end the server-side session.

Because the usable space provided to display a logout menu is different for video vs. audio, Ramp uses two different UI choices:

  • For video playersAuthOverlay renders a persistent "Authenticated" badge in the top-right corner of the player once authenticated successfully. Clicking it opens a keyboard accessible popup menu showing an optional label from the logout service and a "Log out" action.
video-logout
  • For audio players - a custom VideoJS component named VideoJSAuthMenu.js renders a MenuButton component, inserted into the control-bar immediately at the end of the control-bar. Since the control-bar is always visible for audio players (unlike video, where it auto-hides during playback) with enough usable space, this provides a clear UI for this functionality in audio players. It renders a control icon that opens an optional label from the logout service and "Log out" menu pattern similarly.
audio-logout

Both logout actions invoke the same logout sequence in Ramp:

  1. Tears down and disables the current player instance so the authenticated media is removed from playback immediately, and resets the player's aspect ratio back to 16:9 (accommodating the login overlay's layout, since authenticated player may have used a different ratio).
  2. Opens the logout URI in a new tab to clear the server-side session.
  3. Clears the stored token/status back to idle in central state in Context Providers in Ramp, which causes AuthOverlay to re-run its initial probe to re-render the login prompt.

Keyboard accessibility: both logout menu buttons and menu items are reachable via keyboard navigation.

(support from @samvera/ramp — version pending release; implemented in PRs #959 and #979) 🚀🔥


Clone this wiki locally