Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow media embed for certain domains with Global Login #1090

Open
yatesdr opened this issue Oct 22, 2024 · 4 comments
Open

Allow media embed for certain domains with Global Login #1090

yatesdr opened this issue Oct 22, 2024 · 4 comments
Assignees

Comments

@yatesdr
Copy link
Contributor

yatesdr commented Oct 22, 2024

Feature request: Allow embedded media to play when requested by white-listed referers, when the GLOBAL_LOGIN_REQUIRED option is enabled. This allows for the use-case of private media management for use as a back-end in a separate user-controlled system, with some degree of hot-linking protection.

Although request.META['HTTP_REFERER'] can be spoofed and therefore this proposal does not offer perfect security, it's beneficial as an opt-in config in that it's a simple way to allow hosting of videos while not making them fully public (unlisted) or otherwise easily hot-linkable, and limits the ability to browse or otherwise parse media if not authenticated in mediaCMS. Combining this with CORS settings and upstream proxy referer settings can give reasonable assurance that the videos will only be viewed in the intended way.

Proposed solution
I have a working local installation, and the changes roughly consist of:

  1. Add a config variable in cms/settings.py: GLOBAL_LOGIN_ALLOW_EMBED_DOMAINS = ["my-domain.com", "cdn.my-domain.com"]

  2. Further down in cms/settings.py, if the above variable is set, patch additional LOGIN_REQUIRED_IGNORE_PATHS to include r'^/embed.*' and r'^/media/.*' for Django auth middleware, which allows bypassing global auth for these paths.

  • This allows playing embedded media by default from any site, so we must handle the deny / redirect elsewhere.
  1. In files/views.py
    Add logic in embed_media() to check configuration, parse the request's HTTP_REFERER hostname, and deny serving to non-whitelisted domains. After adding the bypass in step 2, all embed links would be served to any referer. This will limit it to the white listed domains only, but does require that the referering system properly set the header.

Alternatives considered: I investigated patching the middleware to allow white-listed domains, but that fix seemed too broad for all the deployed applications. Using this method you can limit the exposure more granularly by path.

My current use-case for this platform is to allow for distributed media management by a number of content managers, and host the relevant media in a content consumption site that will permit viewing the media via iframe embed. We do not own the copyright to every piece of media that will be used, and thus can not allow it to be publicly hosted without some safeguards. End-user authorization is handled by Canvas-LMS in this case, and all pages on the referring system are permitted to embed any media hosted on MediaCMS.

Refinements needed:

  1. The regex expressions need further refinement to limit creative pathing attacks.
  2. Review the error pages, possibly add a response other than redirect to login, to fail without leaking information about the backend service.

I would like feedback on this proposal before creating a pull request:

  1. Is this something you'd like in the main branch?
  2. Is there a better or more secure way to achieve similar functionality?
    I'm happy to chase down other proposed implementations to keep it in line with the creator's vision for this package.
  3. Reviewing the embedded media links, it looks like media/.* is required to basically be open, is there a better way to limit this only to serve media in embeds?
@mgogoulos
Copy link
Contributor

Hi @yatesdr ,

I like your suggestions, it's a workflow I haven't thought of much until now, when you are ready with a draft PR I can test it and gain a better understanding and provide more suggestions. Definitely go ahead and work on a draft PR!

Specifically for item 3. , a sample URL is https://demo.mediacms.io/media/hls/a3c5642e13624149897f193981ebccf3/media-4/segment-0.ts . Because of the identifier used, there's no risk to expose private files (realistically speaking, since it's a uuid), however it's true that ther's no further access control on it, if you see it through the embed and share it then its visible without the HTTP_REFERER, as this file is served through nginx and doesn't know of the custom checks. I guess more complicated functionality around time based tokens that expire and restrict access to the media files, but we could probably work out (or at least brainstorm) something like this as a v2.

@yatesdr
Copy link
Contributor Author

yatesdr commented Oct 23, 2024

I submitted a draft PR, but it seems to have merged with my previous PR for allowing only specific domains to register. I'm sure I messed something up but I'm not sure what exactly, I rarely do PR's on github. Both are fairly minor changes though, so you can review the suggestions and I'll work on separating them for a clean PR when I get a bit more time.

@yatesdr
Copy link
Contributor Author

yatesdr commented Oct 23, 2024

I think I got the PR sorted, you should see a draft for review and further discussion.

@mgogoulos
Copy link
Contributor

Hi, I saw the PR that was opened and closed, but you didn't reopen it after that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants