avalonmediasystem / avalon

Avalon Media System – Samvera Application
http://www.avalonmediasystem.org/
Apache License 2.0
93 stars 51 forks source link

Authentication Flow For Embeds #5376

Closed joncameron closed 11 months ago

joncameron commented 11 months ago

Description

Third-party cookies are being blocked by default in newer versions of Chrome, interfering with the normal flow Avalon uses for authentication for iframe embeds. We'll need to do research and implement something that allows Avalon embeds to live in third-party sites and also for users to have an authenticated session to view restricted content within an embed on a 3rd party site.

We've encountered this in Chrome, but Safari probably has the same issue.

Looking for a cross-browser solution that will work across Chrome, Firefox, and Safari. Chrome is the browser with the tightest default restrictions about third-party cookies.

Possibilities

Current experience

Done Looks Like

joncameron commented 11 months ago

@cjcolvar will post his notes on investigating this.

cjcolvar commented 11 months ago

The Problem: 3rd Party cookies are getting phased out by browsers - Safari already doesn't accept them, Chrome requires an opt-in and will not accept them at some point in mid-2024 Avalon uses 3rd party cookies when a user logs in to view a restricted embedded player on a different domain than Avalon. If possible, we want to find a cross-browser solution that would be backwards compatible with pre-existing embeds.

The auth flow for restricted embedded players without third party cookie support:

  1. Embedded iframe requests embedded player from Avalon and returns message and login button
  2. User clicks login button
  3. Window with Avalon login page pops up
  4. User logs in (if not already) and gets first order session cookie
  5. Popup window closes
  6. Embedded iframe refreshes but browser doesn't send cookie because it is a third-party cookie within the iframe so returns message and login button again

Explored possible solutions:

Partitioned Cookies See https://developer.mozilla.org/en-US/docs/Web/Privacy/Partitioned_cookies and https://developer.chrome.com/docs/privacy-sandbox/chips/ This seems like it should be a workable solution for browsers that implement this (currently only Chrome and Edge). From my understanding, marking cookies as Partitioned should allow the browser to safely receive/send cookies which match the parent page's domain and the embedded iframe's domain as a pair. In this scenario I believe a user would be presented with a login each time they encounter an Avalon embedded player on a different domain even if they already have a session from a different embedded login or with Avalon directly. This would be slightly more inconvenient then the current behavior but might also be a bit of an edge case since it is unlikely to encounter many embeds in the wild.

The auth flow in this scenario:

  1. Embedded iframe requests embedded player from Avalon and returns message and login button
  2. User clicks login button
  3. Window with Avalon login page pops up
  4. User logs in (if not already) and gets token which is passed back to iframe via postMessage
  5. Popup window closes and a background fetch request exchanges the token for a partitioned cookie
  6. Embedded iframe refreshes

Unfortunately I wasn't able to get this working in Chrome. The partitioned cookie would get saved but would not be sent on the iframe refresh request. See this gist for the changes I made: https://gist.github.com/cjcolvar/6c3a73cdb182e11c31c638b98b99dbbb

Storage Access API See https://iiif.io/api/auth/2.0/#user-interaction-at-access-service and https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API This approach seems to allow access to unpartitioned cookies in certain cases in supported browsers. Safari and Firefox have support but Chrome and Edge only support this when embedded ifame and parent page are in the same first party set. First party sets (https://developer.chrome.com/docs/privacy-sandbox/first-party-sets/) are a way to mark sites with different domains as really being part of the same system. This relationship doesn't make sense for Avalon and embedding sites.

I abandoned this approach since it isn't supported in Chrome.

Token only authorization See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage This approach would avoid cookies and instead use tokens. This should work and continue to work as browsers security policies evolve. A down-side to this approach is a user would have to click to view each embed they encounter even if they are on the same site or even page. In order to reduce possible security issues with stealing tokens, the token passed back after login could be a one-time use token. These tokens should be different than streaming tokens and API tokens so additional infrastructure would need to be implemented inside Avalon.

The auth flow in this scenario:

  1. Embedded iframe requests embedded player from Avalon and returns message and login button
  2. User clicks login button
  3. Window with Avalon login page pops up
  4. User logs in (if not already) and gets token which is passed back to iframe via postMessage
  5. Popup window closes
  6. Embedded iframe refreshes with token appended as a query param

Federated Credential Management API (FedCM) See https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API and https://developer.chrome.com/docs/privacy-sandbox/fedcm/ This is an experimental API only supported in Chrome and Edge where the browser mediates the login for embedded iframes which declare allow="identity-credentials-get". Because the browser handles the interaction the issue of third-party cookies is taken on by the browser instead of presenting a login inside the iframe where we might expose credentials to the parent page. This seems like a possible solution but Chrome required enabling a number of experimental settings flags for the demo to work. I didn't explore this further because of its experimental status.

OpenID Connect/OAuth2/JSON Web Tokens (JWT) See https://auth0.com/docs/authenticate/protocols/openid-connect-protocol I didn't investigate these much because they seem like a bigger set of APIs to try and understand. It seems like these are more geared to small sites connecting into auth provided by a large site (like Google) instead of the embed case. It is possible that JWTs might be useful for implementing the token only approach.

View in Repository Only This approach is a short-term workaround where instead of presenting the user with a login button on the embedded iframe Avalon gives a warning message about embeds not working and a link to the item within the repository. This would force the user into a first party interaction with Avalon which would always work. This would defeat the purpose of the embed over a simple link, but it would give the user a clear message and way to get to the content for existing embeds.

See also cypress tests for testing old IIIF auth flow implemented for hyrax-iiif_av: https://gist.github.com/cjcolvar/7d21dc29a148e8098d152e69e243bca5

cjcolvar commented 11 months ago

I tested the IIIF Auth Flow 2 simple login example in Safari and Chrom through BrowserStack and they both worked with default settings. My local Chrome browser (ungoogled-chromium) failed but it has stricter default settings that block 3rd party cookies. This makes me believe that Avalon embeds requiring authentication will work in the current browser ecosystem but this could change by mid-2024 with Chrome's planned sunsetting of 3rd party cookies. I asked in the IIIF #authorization-flow slack channel but wasn't able to get any traction on the future viability of the auth flow 2 spec or possible fixes to deal with the end of 3rd party cookie support.

Given this and the lack of a clear cross-browser solution I think it may be okay to wait until next year to see if a better supported solution emerges. We could add a message to the current black embed screen (when login is required) to suggest a user try enabling 3rd party cookies or try viewing it directly in Avalon if they are having issues logging in.

elynema commented 11 months ago

What does youtube do for restricted embedded videos?

elynema commented 11 months ago

For now, we will leave this will resolving the local storage error and employing 3rd party cookies. We will need to re-evaluate in 2024. So far, no further recommendations from IIIF auth flow community about how to deal with case where 3rd party cookies are fully disabled.

cjcolvar commented 11 months ago

Should look at Fenced Frames again when exploring this in the future.